@nuxt/test-utils
Version:
Test utilities for Nuxt
162 lines (158 loc) • 4.65 kB
JavaScript
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 };