@nuxt/test-utils 3.20.1 → 3.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,67 @@
1
+ import destr from 'destr';
2
+ import { snakeCase } from 'scule';
3
+ import { pathToFileURL } from 'node:url';
4
+ import { resolveModulePath } from 'exsolve';
5
+
6
+ function getEnv(key, opts) {
7
+ const env = opts.env ?? process.env;
8
+ const envKey = snakeCase(key).toUpperCase();
9
+ return destr(
10
+ env[opts.prefix + envKey] ?? env[opts.altPrefix + envKey]
11
+ );
12
+ }
13
+ function _isObject(input) {
14
+ return typeof input === "object" && !Array.isArray(input);
15
+ }
16
+ function applyEnv(obj, opts, parentKey = "") {
17
+ for (const key in obj) {
18
+ const subKey = parentKey ? `${parentKey}_${key}` : key;
19
+ const envValue = getEnv(subKey, opts);
20
+ if (_isObject(obj[key])) {
21
+ if (_isObject(envValue)) {
22
+ obj[key] = { ...obj[key], ...envValue };
23
+ applyEnv(obj[key], opts, subKey);
24
+ } else if (envValue === void 0) {
25
+ applyEnv(obj[key], opts, subKey);
26
+ } else {
27
+ obj[key] = envValue ?? obj[key];
28
+ }
29
+ } else {
30
+ obj[key] = envValue ?? obj[key];
31
+ }
32
+ }
33
+ return obj;
34
+ }
35
+ async function loadKit(rootDir) {
36
+ try {
37
+ const kitPath = resolveModulePath("@nuxt/kit", { from: tryResolveNuxt(rootDir) || rootDir });
38
+ let kit = await import(pathToFileURL(kitPath).href);
39
+ if (!kit.writeTypes) {
40
+ kit = {
41
+ ...kit,
42
+ writeTypes: () => {
43
+ throw new Error("`writeTypes` is not available in this version of `@nuxt/kit`. Please upgrade to v3.7 or newer.");
44
+ }
45
+ };
46
+ }
47
+ return kit;
48
+ } catch (e) {
49
+ if (e.toString().includes("Cannot find module '@nuxt/kit'")) {
50
+ throw new Error(
51
+ "`@nuxt/test-utils` requires `@nuxt/kit` to be installed in your project. Try installing `nuxt` v3+ or `@nuxt/bridge` first."
52
+ );
53
+ }
54
+ throw e;
55
+ }
56
+ }
57
+ function tryResolveNuxt(rootDir) {
58
+ for (const pkg of ["nuxt-nightly", "nuxt", "nuxt3", "nuxt-edge"]) {
59
+ const path = resolveModulePath(pkg, { from: rootDir, try: true });
60
+ if (path) {
61
+ return path;
62
+ }
63
+ }
64
+ return null;
65
+ }
66
+
67
+ export { applyEnv as a, loadKit as l };
@@ -91,8 +91,8 @@ async function startServer(options = {}) {
91
91
  PORT: String(port),
92
92
  HOST: host,
93
93
  NODE_ENV: "development",
94
- ...options.env,
95
- ...ctx.options.env
94
+ ...ctx.options.env,
95
+ ...options.env
96
96
  }
97
97
  }
98
98
  });
@@ -128,8 +128,8 @@ async function startServer(options = {}) {
128
128
  PORT: String(port),
129
129
  HOST: host,
130
130
  NODE_ENV: "test",
131
- ...options.env,
132
- ...ctx.options.env
131
+ ...ctx.options.env,
132
+ ...options.env
133
133
  }
134
134
  }
135
135
  }
@@ -1,8 +1,8 @@
1
- import { u as useTestContext, d as url, c as createTestContext, a as startServer, b as stopServer, s as setTestContext } from './test-utils.CtwoJP76.mjs';
1
+ import { u as useTestContext, d as url, c as createTestContext, a as startServer, b as stopServer, s as setTestContext } from './test-utils.C_clWQBc.mjs';
2
2
  import { existsSync, promises } from 'node:fs';
3
3
  import { resolve } from 'node:path';
4
4
  import { defu } from 'defu';
5
- import * as _kit from '@nuxt/kit';
5
+ import { l as loadKit } from './test-utils.BIY9XRkB.mjs';
6
6
 
7
7
  async function createBrowser() {
8
8
  const ctx = useTestContext();
@@ -57,7 +57,6 @@ async function waitForHydration(page, url2, waitUntil) {
57
57
  }
58
58
  }
59
59
 
60
- const kit = _kit.default || _kit;
61
60
  const isNuxtApp = (dir) => {
62
61
  return existsSync(dir) && (existsSync(resolve(dir, "pages")) || existsSync(resolve(dir, "nuxt.config.js")) || existsSync(resolve(dir, "nuxt.config.mjs")) || existsSync(resolve(dir, "nuxt.config.cjs")) || existsSync(resolve(dir, "nuxt.config.ts")) || existsSync(resolve(dir, ".config", "nuxt.js")) || existsSync(resolve(dir, ".config", "nuxt.mjs")) || existsSync(resolve(dir, ".config", "nuxt.cjs")) || existsSync(resolve(dir, ".config", "nuxt.ts")));
63
62
  };
@@ -91,7 +90,8 @@ async function loadFixture() {
91
90
  });
92
91
  }
93
92
  if (ctx.options.build) {
94
- ctx.nuxt = await kit.loadNuxt({
93
+ const { loadNuxt } = await loadKit(ctx.options.rootDir);
94
+ ctx.nuxt = await loadNuxt({
95
95
  cwd: ctx.options.rootDir,
96
96
  dev: ctx.options.dev,
97
97
  overrides: ctx.options.nuxtConfig,
@@ -107,10 +107,11 @@ async function loadFixture() {
107
107
  }
108
108
  async function buildFixture() {
109
109
  const ctx = useTestContext();
110
- const prevLevel = kit.logger.level;
111
- kit.logger.level = ctx.options.logLevel;
112
- await kit.buildNuxt(ctx.nuxt);
113
- kit.logger.level = prevLevel;
110
+ const { buildNuxt, logger } = await loadKit(ctx.options.rootDir);
111
+ const prevLevel = logger.level;
112
+ logger.level = ctx.options.logLevel;
113
+ await buildNuxt(ctx.nuxt);
114
+ logger.level = prevLevel;
114
115
  }
115
116
 
116
117
  async function setupBun(hooks) {
@@ -0,0 +1,32 @@
1
+ function isMessage(message) {
2
+ return message !== null && typeof message === "object" && "type" in message && message.type !== null && typeof message.type === "string" && "payload" in message && message.payload !== null && typeof message.payload === "object";
3
+ }
4
+ function createVitestTestSummary() {
5
+ return {
6
+ failedCount: 0,
7
+ passedCount: 0,
8
+ totalCount: 0
9
+ };
10
+ }
11
+ function sendMessageToHost(type, payload) {
12
+ process.send?.({ type, payload });
13
+ }
14
+ function listenHostMessages(listener) {
15
+ process.on("message", (message) => {
16
+ if (isMessage(message)) {
17
+ listener(message);
18
+ }
19
+ });
20
+ }
21
+ function sendMessageToCli(cli, type, payload) {
22
+ cli.send({ type, payload });
23
+ }
24
+ function listenCliMessages(cli, listener) {
25
+ cli.on("message", (message) => {
26
+ if (isMessage(message)) {
27
+ listener(message);
28
+ }
29
+ });
30
+ }
31
+
32
+ export { listenHostMessages as a, sendMessageToHost as b, createVitestTestSummary as c, listenCliMessages as l, sendMessageToCli as s };
@@ -116,4 +116,4 @@ interface TestHooks {
116
116
  }
117
117
 
118
118
  export { $fetch as $, createBrowser as c, createPage as d, stopServer as e, fetch as f, getBrowser as g, startServer as s, url as u, waitForHydration as w };
119
- export type { GotoOptions as G, NuxtPage as N, StartServerOptions as S, TestOptions as T, TestContext as a, TestHooks as b, TestRunner as h };
119
+ export type { GotoOptions as G, NuxtPage as N, StartServerOptions as S, TestOptions as T, TestHooks as a, TestContext as b, TestRunner as h };
@@ -83,9 +83,6 @@ async function setupWindow(win, environmentOptions) {
83
83
  return _fetch(input, _init);
84
84
  };
85
85
  win.$fetch = createFetch({ fetch: win.fetch, Headers: win.Headers });
86
- win.$fetch.create = (options = {}) => {
87
- return createFetch({ fetch: win.fetch, Headers: win.Headers, ...options });
88
- };
89
86
  win.__registry = registry;
90
87
  win.__app = h3App;
91
88
  const timestamp = Date.now();
@@ -0,0 +1,2 @@
1
+
2
+ export { };
@@ -0,0 +1,78 @@
1
+ import { importModule } from 'local-pkg';
2
+ import { getPort } from 'get-port-please';
3
+ import { a as listenHostMessages, b as sendMessageToHost } from '../shared/test-utils.DDUpsMYL.mjs';
4
+
5
+ function createCustomReporter(onVitestInit) {
6
+ let ctx = void 0;
7
+ function getVitestUiUrl() {
8
+ if (!ctx.config.ui) return void 0;
9
+ const protocol = ctx.vite.config.server.https ? "https:" : "http:";
10
+ const host = ctx.config.api.host || "localhost";
11
+ const port = ctx.config.api.port;
12
+ const uiBase = ctx.config.uiBase;
13
+ return `${protocol}//${host}:${port}${uiBase}`;
14
+ }
15
+ function toUpdatedResult() {
16
+ const files = ctx.state.getFiles();
17
+ return {
18
+ failedCount: files.filter((f) => f.result?.state === "fail").length ?? 0,
19
+ passedCount: files.filter((f) => f.result?.state === "pass").length ?? 0,
20
+ totalCount: files.length ?? 0
21
+ };
22
+ }
23
+ function toFinishedResult() {
24
+ return toUpdatedResult();
25
+ }
26
+ return {
27
+ onInit(_ctx) {
28
+ ctx = _ctx;
29
+ onVitestInit(ctx);
30
+ sendMessageToHost("started", { uiUrl: getVitestUiUrl() });
31
+ },
32
+ onTestRunStart() {
33
+ sendMessageToHost("updated", toUpdatedResult());
34
+ },
35
+ onTaskUpdate() {
36
+ sendMessageToHost("updated", toUpdatedResult());
37
+ },
38
+ onFinished() {
39
+ sendMessageToHost("finished", toFinishedResult());
40
+ }
41
+ };
42
+ }
43
+ async function main() {
44
+ const {
45
+ apiPorts,
46
+ watchMode
47
+ } = await new Promise((resolve) => {
48
+ listenHostMessages(({ type, payload }) => {
49
+ if (type === "start") resolve(payload);
50
+ });
51
+ });
52
+ const port = apiPorts ? await getPort({ ports: apiPorts }) : void 0;
53
+ const { startVitest } = await importModule("vitest/node");
54
+ const customReporter = createCustomReporter((vitest2) => {
55
+ listenHostMessages(async ({ type, payload }) => {
56
+ if (type === "stop") {
57
+ await vitest2.exit(payload.force);
58
+ process.exit();
59
+ }
60
+ });
61
+ });
62
+ const vitest = await startVitest("test", [], watchMode ? {
63
+ passWithNoTests: true,
64
+ ui: true,
65
+ watch: true,
66
+ open: false,
67
+ api: { port }
68
+ } : { ui: false, watch: false }, {
69
+ test: {
70
+ reporters: ["default", customReporter]
71
+ }
72
+ });
73
+ if (!watchMode) {
74
+ await vitest.exit();
75
+ process.exit();
76
+ }
77
+ }
78
+ main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuxt/test-utils",
3
- "version": "3.20.1",
3
+ "version": "3.22.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/nuxt/test-utils.git"
@@ -57,7 +57,7 @@
57
57
  "lint": "eslint .",
58
58
  "lint:fix": "eslint . --fix",
59
59
  "test": "pnpm test:types && pnpm test:unit && pnpm test:examples",
60
- "test:examples": "pnpm --filter '!example-app-cucumber' --filter '!example-app-jest' -r test && pnpm --filter example-app-cucumber -r test",
60
+ "test:examples": "pnpm --filter '!example-app-cucumber' --filter '!example-app-jest' --filter '!example-app-bun' -r test && pnpm --filter example-app-cucumber -r test",
61
61
  "test:knip": "knip",
62
62
  "test:engines": "pnpm installed-check --no-workspaces --ignore-dev",
63
63
  "test:types": "vue-tsc --noEmit",
@@ -67,40 +67,41 @@
67
67
  "dev:prepare": "nuxt prepare && unbuild --stub && pnpm -r dev:prepare"
68
68
  },
69
69
  "dependencies": {
70
- "@nuxt/kit": "^4.1.3",
71
- "c12": "^3.3.1",
70
+ "@nuxt/kit": "^3.20.2",
71
+ "c12": "^3.3.3",
72
72
  "consola": "^3.4.2",
73
73
  "defu": "^6.1.4",
74
74
  "destr": "^2.0.5",
75
75
  "estree-walker": "^3.0.3",
76
- "fake-indexeddb": "^6.2.4",
76
+ "exsolve": "^1.0.8",
77
+ "fake-indexeddb": "^6.2.5",
77
78
  "get-port-please": "^3.2.0",
78
79
  "h3": "^1.15.4",
79
80
  "local-pkg": "^1.1.2",
80
- "magic-string": "^0.30.19",
81
+ "magic-string": "^0.30.21",
81
82
  "node-fetch-native": "^1.6.7",
82
- "node-mock-http": "^1.0.3",
83
- "ofetch": "^1.4.1",
83
+ "node-mock-http": "^1.0.4",
84
+ "ofetch": "^1.5.1",
84
85
  "pathe": "^2.0.3",
85
86
  "perfect-debounce": "^2.0.0",
86
87
  "radix3": "^1.1.2",
87
88
  "scule": "^1.3.0",
88
89
  "std-env": "^3.10.0",
89
- "tinyexec": "^1.0.1",
90
+ "tinyexec": "^1.0.2",
90
91
  "ufo": "^1.6.1",
91
- "unplugin": "^2.3.10",
92
+ "unplugin": "^2.3.11",
92
93
  "vitest-environment-nuxt": "^1.0.1",
93
- "vue": "^3.5.22"
94
+ "vue": "^3.5.26"
94
95
  },
95
96
  "devDependencies": {
96
- "@cucumber/cucumber": "12.2.0",
97
+ "@cucumber/cucumber": "12.5.0",
97
98
  "@jest/globals": "30.2.0",
98
- "@nuxt/devtools-kit": "2.6.5",
99
- "@nuxt/eslint-config": "1.9.0",
100
- "@nuxt/schema": "4.1.3",
101
- "@playwright/test": "1.56.1",
99
+ "@nuxt/devtools-kit": "2.7.0",
100
+ "@nuxt/eslint-config": "1.12.1",
101
+ "@nuxt/schema": "4.2.2",
102
+ "@playwright/test": "1.57.0",
102
103
  "@testing-library/vue": "8.1.0",
103
- "@types/bun": "1.3.0",
104
+ "@types/bun": "1.3.5",
104
105
  "@types/estree": "1.0.8",
105
106
  "@types/jsdom": "27.0.0",
106
107
  "@types/node": "latest",
@@ -108,22 +109,22 @@
108
109
  "@vue/test-utils": "2.4.6",
109
110
  "changelogen": "0.6.2",
110
111
  "compatx": "0.2.0",
111
- "eslint": "9.38.0",
112
+ "eslint": "9.39.2",
112
113
  "installed-check": "9.3.0",
113
- "knip": "5.66.2",
114
- "nitropack": "2.12.7",
115
- "nuxt": "4.1.3",
116
- "pkg-pr-new": "0.0.60",
117
- "playwright-core": "1.56.1",
118
- "rollup": "4.52.5",
114
+ "knip": "5.78.0",
115
+ "nitropack": "2.12.9",
116
+ "nuxt": "4.2.2",
117
+ "pkg-pr-new": "0.0.62",
118
+ "playwright-core": "1.57.0",
119
+ "rollup": "4.54.0",
119
120
  "semver": "7.7.3",
120
121
  "typescript": "5.9.3",
121
122
  "unbuild": "latest",
122
- "unimport": "5.5.0",
123
- "vite": "7.1.11",
123
+ "unimport": "5.6.0",
124
+ "vite": "7.3.0",
124
125
  "vitest": "3.2.4",
125
- "vue-router": "4.6.3",
126
- "vue-tsc": "3.1.1"
126
+ "vue-router": "4.6.4",
127
+ "vue-tsc": "3.2.1"
127
128
  },
128
129
  "peerDependencies": {
129
130
  "@cucumber/cucumber": "^10.3.1 || >=11.0.0",
@@ -169,31 +170,18 @@
169
170
  }
170
171
  },
171
172
  "resolutions": {
172
- "@cucumber/cucumber": "12.2.0",
173
- "@nuxt/kit": "^4.1.3",
174
- "@nuxt/schema": "4.1.3",
173
+ "@cucumber/cucumber": "12.5.0",
174
+ "@nuxt/schema": "4.2.2",
175
175
  "@nuxt/test-utils": "workspace:*",
176
- "@types/node": "22.18.8",
177
- "rollup": "4.52.5",
178
- "vite": "7.1.11",
179
- "vite-node": "3.2.4",
176
+ "@types/node": "24.10.4",
177
+ "rollup": "4.54.0",
178
+ "vite": "7.3.0",
179
+ "vite-node": "5.2.0",
180
180
  "vitest": "3.2.4",
181
- "vue": "^3.5.22"
181
+ "vue": "^3.5.26"
182
182
  },
183
183
  "engines": {
184
184
  "node": "^20.0.0 || ^22.0.0 || >=24.0.0"
185
185
  },
186
- "packageManager": "pnpm@10.18.3",
187
- "pnpm": {
188
- "onlyBuiltDependencies": [
189
- "@tailwindcss/oxide",
190
- "better-sqlite3"
191
- ],
192
- "ignoredBuiltDependencies": [
193
- "esbuild",
194
- "oxc-resolver",
195
- "unrs-resolver",
196
- "vue-demi"
197
- ]
198
- }
186
+ "packageManager": "pnpm@10.26.2"
199
187
  }