UNPKG

@nuxt/test-utils

Version:
162 lines (158 loc) 4.65 kB
import { x } from 'tinyexec'; import { getRandomPort, waitForPort } from 'get-port-please'; import { $fetch as $fetch$1, fetch as fetch$1 } from 'ofetch'; import { resolve as resolve$1 } from 'pathe'; import { withTrailingSlash, joinURL } from 'ufo'; import { resolve } from 'node:path'; import { defu } from 'defu'; import { isWindows } from 'std-env'; let currentContext; function createTestContext(options) { const _options = defu(options, { testDir: resolve(process.cwd(), "test"), fixture: "fixture", configFile: "nuxt.config", setupTimeout: isWindows ? 24e4 : 12e4, teardownTimeout: 3e4, dev: !!JSON.parse(process.env.NUXT_TEST_DEV || "false"), logLevel: 1, server: true, build: options.browser !== false || options.server !== false, env: {}, nuxtConfig: { // suppress compatibility date warning for runtime environment tests compatibilityDate: "2024-04-03" }, browserOptions: { type: "chromium" } }); if (!_options.dev) { _options.env.NODE_ENV ||= "production"; } if (_options.host) { _options.build = false; _options.server = false; } if (process.env.VITEST === "true") { _options.runner ||= "vitest"; } else if (process.env.JEST_WORKER_ID) { _options.runner ||= "jest"; } return setTestContext({ options: _options, url: withTrailingSlash(_options.host) }); } function useTestContext() { recoverContextFromEnv(); if (!currentContext) { throw new Error("No context is available. (Forgot calling setup or createContext?)"); } return currentContext; } function setTestContext(context) { currentContext = context; return currentContext; } function isDev() { const ctx = useTestContext(); return ctx.options.dev; } function recoverContextFromEnv() { if (!currentContext && process.env.NUXT_TEST_CONTEXT) { setTestContext(JSON.parse(process.env.NUXT_TEST_CONTEXT || "{}")); } } function exposeContextToEnv() { const { options, browser, url } = currentContext; process.env.NUXT_TEST_CONTEXT = JSON.stringify({ options, browser, url }); } async function startServer(options = {}) { const ctx = useTestContext(); await stopServer(); const host = "127.0.0.1"; const port = ctx.options.port || await getRandomPort(host); ctx.url = `http://${host}:${port}/`; if (ctx.options.dev) { ctx.serverProcess = x("nuxi", ["_dev"], { throwOnError: true, nodeOptions: { cwd: ctx.nuxt.options.rootDir, stdio: "inherit", env: { ...process.env, _PORT: String(port), // Used by internal _dev command PORT: String(port), HOST: host, NODE_ENV: "development", ...options.env, ...ctx.options.env } } }); await waitForPort(port, { retries: 32, host }).catch(() => { }); let lastError; for (let i = 0; i < 150; i++) { await new Promise((resolve2) => setTimeout(resolve2, 100)); try { const res = await $fetch(ctx.nuxt.options.app.baseURL, { responseType: "text" }); if (!res.includes("__NUXT_LOADING__")) { return; } } catch (e) { lastError = e; } } ctx.serverProcess.kill(); throw lastError || new Error("Timeout waiting for dev server!"); } else { const outputDir = ctx.nuxt ? ctx.nuxt.options.nitro.output.dir : ctx.options.nuxtConfig.nitro.output.dir; ctx.serverProcess = x( "node", [resolve$1(outputDir, "server/index.mjs")], { throwOnError: true, nodeOptions: { stdio: "inherit", env: { ...process.env, PORT: String(port), HOST: host, NODE_ENV: "test", ...options.env, ...ctx.options.env } } } ); await waitForPort(port, { retries: 20, host }); } } async function stopServer() { const ctx = useTestContext(); if (ctx.serverProcess) { ctx.serverProcess.kill(); } } function fetch(path, options) { return fetch$1(url(path), options); } const $fetch = function(path, options) { return $fetch$1(url(path), options); }; function url(path) { const ctx = useTestContext(); if (!ctx.url) { throw new Error("url is not available (is server option enabled?)"); } if (path.startsWith(ctx.url)) { return path; } return joinURL(ctx.url, path); } export { $fetch as $, startServer as a, stopServer as b, createTestContext as c, url as d, exposeContextToEnv as e, fetch as f, isDev as i, recoverContextFromEnv as r, setTestContext as s, useTestContext as u };