UNPKG

@nuxt/test-utils

Version:
213 lines (209 loc) 6.34 kB
import { defineConfig } from 'vite'; import { setupDotenv } from 'c12'; import { defu } from 'defu'; import { createResolver } from '@nuxt/kit'; import destr from 'destr'; import { snakeCase } from 'scule'; function getEnv(key, opts) { const env = opts.env ?? process.env; const envKey = snakeCase(key).toUpperCase(); return destr( env[opts.prefix + envKey] ?? env[opts.altPrefix + envKey] ); } function _isObject(input) { return typeof input === "object" && !Array.isArray(input); } function applyEnv(obj, opts, parentKey = "") { for (const key in obj) { const subKey = parentKey ? `${parentKey}_${key}` : key; const envValue = getEnv(subKey, opts); if (_isObject(obj[key])) { if (_isObject(envValue)) { obj[key] = { ...obj[key], ...envValue }; applyEnv(obj[key], opts, subKey); } else if (envValue === void 0) { applyEnv(obj[key], opts, subKey); } else { obj[key] = envValue ?? obj[key]; } } else { obj[key] = envValue ?? obj[key]; } } return obj; } async function startNuxtAndGetViteConfig(rootDir = process.cwd(), options = {}) { const { loadNuxt, buildNuxt } = await import('@nuxt/kit'); const nuxt = await loadNuxt({ cwd: rootDir, dev: false, dotenv: defu(options.dotenv, { cwd: rootDir, fileName: ".env.test" }), defaults: { // suppress compatibility date warning for runtime environment tests compatibilityDate: "2024-04-03" }, overrides: defu( { appId: "nuxt-app", buildId: "test", ssr: false, test: true, modules: ["@nuxt/test-utils/module"] }, options.overrides ) }); if (!nuxt.options._installedModules.find((i) => i?.meta?.name === "@nuxt/test-utils")) { throw new Error( "Failed to load `@nuxt/test-utils/module`. You may need to add it to your nuxt.config." ); } const promise = new Promise((resolve, reject) => { nuxt.hook("vite:configResolved", (viteConfig, { isClient }) => { if (isClient) { resolve({ nuxt, viteConfig }); throw new Error("_stop_"); } }); buildNuxt(nuxt).catch((err) => { if (!err.toString().includes("_stop_")) { reject(err); } }); }).finally(() => nuxt.close()); return promise; } const excludedPlugins = [ "nuxt:import-protection", "nuxt:import-conditions", "vite-plugin-checker" ]; async function getVitestConfigFromNuxt(options, loadNuxtOptions = {}) { const { rootDir = process.cwd(), ..._overrides } = loadNuxtOptions.overrides || {}; if (!options) { options = await startNuxtAndGetViteConfig(rootDir, { dotenv: loadNuxtOptions.dotenv, overrides: { test: true, ..._overrides } }); } options.viteConfig.plugins = (options.viteConfig.plugins || []).filter((p) => !p || !("name" in p) || !excludedPlugins.includes(p.name)); const resolvedConfig = defu( // overrides { define: { ["process.env.NODE_ENV"]: "process.env.NODE_ENV" }, test: { dir: process.cwd(), environmentOptions: { nuxtRuntimeConfig: applyEnv(structuredClone(options.nuxt.options.runtimeConfig), { prefix: "NUXT_", env: await setupDotenv(defu(loadNuxtOptions.dotenv, { cwd: rootDir, fileName: ".env.test" })) }), nuxtRouteRules: defu( {}, options.nuxt.options.routeRules, options.nuxt.options.nitro?.routeRules ) }, environmentMatchGlobs: [ ["**/*.nuxt.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}", "nuxt"], ["{test,tests}/nuxt/**.*", "nuxt"] ], server: { deps: { inline: [ // vite-node defaults /\/node_modules\/(.*\/)?(nuxt|nuxt3|nuxt-nightly)\//, /^#/, // additional deps "@nuxt/test-utils", "@nuxt/test-utils-nightly", "@nuxt/test-utils-edge", "vitest-environment-nuxt", ...options.nuxt.options.build.transpile.filter( (r) => typeof r === "string" || r instanceof RegExp ) ] } }, deps: { optimizer: { web: { enabled: false } } } } }, { server: { middlewareMode: false }, plugins: [ { name: "disable-auto-execute", enforce: "pre", transform(code, id) { if (id.match(/nuxt(3|-nightly)?\/.*\/entry\./)) { return code.replace( /(?<!vueAppPromise = )entry\(\)/, "Promise.resolve()" ); } } } ] }, // resolved vite config options.viteConfig, // (overrideable) defaults { test: { environmentOptions: { nuxt: { rootId: options.nuxt.options.app.rootId || void 0, mock: { intersectionObserver: true, indexedDb: false } } } } } ); delete resolvedConfig.define["process.browser"]; delete resolvedConfig.customLogger; if (!Array.isArray(resolvedConfig.test.setupFiles)) { resolvedConfig.test.setupFiles = [resolvedConfig.test.setupFiles].filter(Boolean); } const resolver = createResolver(import.meta.url); resolvedConfig.test.setupFiles.unshift(resolver.resolve("./runtime/entry")); return resolvedConfig; } function defineVitestConfig(config = {}) { return defineConfig(async () => { if (process.env.__NUXT_VITEST_RESOLVED__) return config; const overrides = config.test?.environmentOptions?.nuxt?.overrides || {}; overrides.rootDir = config.test?.environmentOptions?.nuxt?.rootDir; if (config.test?.setupFiles && !Array.isArray(config.test.setupFiles)) { config.test.setupFiles = [config.test.setupFiles].filter(Boolean); } return defu( config, await getVitestConfigFromNuxt(void 0, { dotenv: config.test?.environmentOptions?.nuxt?.dotenv, overrides: structuredClone(overrides) }) ); }); } export { defineVitestConfig, getVitestConfigFromNuxt };