Nuxt Test Utils

repository·main·Indexed 19 days ago

https://github.com/nuxt/test-utils

Test utilities for Nuxt providing first-class support for end-to-end (e2e) and unit testing. Features include Vitest configuration via defineVitestConfig and defineVitestProject, ESLint integration with createConfigForNuxt, and a comprehensive E2E testing framework with server management, browser automation via Playwright, and test context handling for runners like Vitest, Jest, Bun, and Cucumber.

Tokens
9.2K
Snippets
31
Records
35
Agent score
65%

What's inside @nuxt/test-utils

  1. Configure ESLint with createConfigForNuxt

    main

    The project uses @nuxt/eslint-config/flat to generate a Nuxt-compatible ESLint configuration via the createConfigForNuxt function. This allows you to enable specific Nuxt features and define which directories should be linted.

    Configuration Options

    features An object to enable or disable specific ESLint feature sets:

    • tooling: Enables tooling-related rules.
    • stylistic: Enables stylistic rules.

    dirs An object defining the directories to be included in the linting process. The src key accepts an array of paths.

    .append() After calling createConfigForNuxt, you can use the .append() method to add custom ESLint rules to the generated configuration.

    import { createConfigForNuxt } from '@nuxt/eslint-config/flat'
    
    export default createConfigForNuxt({
      features: {
        tooling: true,
        stylistic: true,
      },
      dirs: {
        src: ['./examples/app-vitest'],
      },
    }).append({
      rules: {
        'vue/multi-word-component-names': 'off',
      },
    })
  2. Import the Vitest environment from @nuxt/test-utils

    main

    The @nuxt/test-utils package exports the default Vitest environment and its associated types. This environment allows you to run Vitest tests within a Nuxt context.

    To use the environment in your Vitest configuration, you can import the default export or use the exported types for custom environment implementations.

    import vitestEnvironment from '@nuxt/test-utils/vitest-environment'
  3. Setup import mocking with setupImportMocking()

    main

    To enable mocking of Nuxt imports (such as useRuntimeConfig, useAppConfig, etc.) in your tests, use the setupImportMocking function. This function works as a macro that transforms mockNuxtImport() calls into vi.mock() calls, allowing you to intercept and provide custom implementations for Nuxt-specific auto-imports.

    When called, it performs the following setup:

    • Hooks into the Nuxt lifecycle to capture component and import contexts.
    • Configures Vite to use a specialized mock plugin.
    • Adjusts Nuxt's ignore patterns to ensure .spec. and .test. files are processed.
    • Filters out test files from being registered as actual Nuxt plugins during app:resolve.
    • Removes setInterval from imports:sources to prevent mocking conflicts with native timers.
    import { setupImportMocking } from '@nuxt/test-utils/module'
    
    // Inside your Nuxt module or test setup environment
    export default defineNuxtModule({
      setup(nuxt) {
        setupImportMocking(nuxt)
      }
    })
  4. Import expect from Nuxt Test Utils Playwright

    main

    To maintain consistency with the extended test object, you should import expect directly from the @nuxt/test-utils/playwright entrypoint. This ensures you are using the version compatible with the extended Playwright environment.

    import { test, expect } from '@nuxt/test-utils/playwright'
    
    test('example', async ({ page }) => {
      await page.goto('http://localhost:3000')
      await expect(page.locator('h1')).toHaveText('Hello Nuxt')
    })
  5. Initialize E2E tests with createTest()

    main

    Use createTest to generate a set of test hooks (beforeAll, afterAll, beforeEach, afterEach) and a test context (ctx) based on your provided TestOptions. This is useful for manual control over the Nuxt testing lifecycle in different test runners.

    Supported options include:

    • fixture: Whether to load a fixture.
    • build: Whether to build the fixture.
    • server: Whether to start a server (can accept an environment configuration).
    • waitFor: A delay in milliseconds to wait before starting tests.
    • browser: Whether to initialize a browser instance.
    • teardownTimeout: A timeout in milliseconds for teardown operations.
    • teardown: An array of functions to run during teardown.
    • runner: Specifies the test runner (e.g., vitest, jest, bun, cucumber) to determine how hooks are applied.
    import { createTest } from '@nuxt/test-utils/e2e'
    
    const { beforeEach, afterEach, beforeAll, afterAll, ctx } = createTest({
      build: true,
      server: true,
      browser: true,
      teardownTimeout: 5000
    })
    
    // Use these hooks in your test runner's lifecycle configuration
  6. Render components in the Nuxt environment with renderSuspended

    main

    Use renderSuspended to mount Vue components within a Nuxt environment. This utility is essential for testing components that use async setup(), rely on Nuxt-specific injections, or require access to Nuxt plugins.

    renderSuspended acts as a wrapper around the render function from @testing-library/vue. Because it handles the Nuxt lifecycle and suspension, you should use it alongside @testing-library/vue utilities (like screen) to interact with the rendered output.

    Key features:

    • Supports async component setup.
    • Provides access to Nuxt plugin injections.
    • Allows setting a specific route via options.
    • Returns a wrapper that includes a rerender method to update props asynchronously.
    import { renderSuspended } from '@nuxt/test-utils/runtime'
    
    // Example 1: Rendering a single component
    it('can render some component', async () => {
      const { html } = await renderSuspended(SomeComponent)
      expect(html()).toMatchInlineSnapshot(
        'This is an auto-imported component'
      )
    })
    
    // Example 2: Rendering an App with a specific route
    import { screen } from '@testing-library/vue'
    
    it('can also mount an app', async () => {
      const { html } = await renderSuspended(App, { route: '/test' })
      expect(screen.getByRole('link', { name: 'Test Link' })).toBeVisible()
    })
  7. Define a single Nuxt project with defineVitestProject

    main

    If you are working within a Vitest workspace and want to define a specific project that uses the Nuxt environment, use defineVitestProject. This ensures the project is correctly configured with the nuxt environment and necessary setup files.

    import { defineVitestProject } from '@nuxt/test-utils/config'
    import type { TestProjectInlineConfiguration }
    
    export default defineVitestProject({
      test: {
        environment: 'nuxt',
        // other project specific settings
      }
    } as TestProjectInlineConfiguration)
  8. Configure E2E test runner setup with setup()

    main

    The setup function is the primary entry point for configuring end-to-end tests. It automatically detects the appropriate runner setup (Vitest, Jest, Bun, or Cucumber) based on the runner option in your TestOptions and applies the necessary lifecycle hooks.

    Note for Vitest users: If you are running E2E tests, avoid using defineVitestConfig or defineVitestProject, as these are intended for client-environment tests. Instead, follow the official Nuxt documentation for E2E setup.

    import { setup } from '@nuxt/test-utils/e2e'
    
    await setup({
      runner: 'vitest',
      build: true,
      server: true,
      browser: true
    })
  9. Mock Nuxt auto-imports with mockNuxtImport

    main

    Use mockNuxtImport to mock Nuxt's auto-import functionality. This allows you to intercept calls to composables or other auto-imported functions.

    Usage Patterns:

    • Mock by name: Pass the string name of the import and a factory function.
    • Mock by reference: Pass the actual function/object and a factory function.
    • Partial mock: Use the factory to wrap the original implementation (e.g., with vi.fn()).

    Note: mockNuxtImport is a macro and must be transpiled by your build tool to work correctly.

    import { mockNuxtImport } from '@nuxt/test-utils/runtime'
    
    // Mocking by name
    mockNuxtImport('useStorage', () => {
     return () => {
       return { value: 'mocked storage' }
     }
    })
    
    // Mocking by reference
    // (Assuming useStorage is available in the scope)
    // mockNuxtImport(useStorage, () => {
    //   return () => {
    //     return { value: 'mocked storage' }
    //   }
    // })
    
    // Making a partial mock with the original implementation
    // mockNuxtImport('useRoute', original => vi.fn(original))
  10. Access the current test context with useTestContext()

    main

    Use useTestContext() to retrieve the currently active TestContext.

    Note: This function will throw an error if no context has been initialized via createTestContext() or setTestContext(). If you are running in an environment where the context was serialized to an environment variable, call recoverContextFromEnv() first to restore it.

    import { useTestContext } from '@nuxt/test-utils'
    
    const ctx = useTestContext()
    console.log(ctx.url)
  11. Use the enhanced goto() method in Playwright tests

    main

    The extended test object provides a goto method that simplifies navigating to URLs in a Nuxt application. Unlike the standard Playwright page.goto, this version automatically handles Nuxt hydration.

    When you call goto(url, options), it performs the standard navigation and then waits for Nuxt hydration to complete if the waitUntil option is set to 'hydration' or 'route'. Note that these specific values are intercepted and handled internally to ensure the test waits for the Nuxt application to be interactive.

    import { test } from '@nuxt/test-utils/playwright'
    
    test('my test', async ({ page, goto }) => {
      // This will navigate and wait for Nuxt hydration
      await goto('http://localhost:3000', { waitUntil: 'hydration' })
    })
  12. Import runtime utilities from @nuxt/test-utils/runtime

    main

    The stubs/vitest-environment-nuxt/utils.mjs file acts as a re-export entry point for the @nuxt/test-utils/runtime package. When working with Vitest environments for Nuxt, you can use this entry point to access the runtime utilities provided by the test utils package.

    export * from '@nuxt/test-utils/runtime'