@nuxt/test-utils-nightly 4.0.0-1701501480.7490334 → 4.0.0-1702910449.8cf01bd

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.
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## Overview
6
6
 
7
- Nuxt offers first-class support for e2e and unit testing of your Nuxt applications. `@nuxt/test-utils` currently contains e2e test utilities allowing you to test your app in production/development environments, and [`nuxt-vitest`](https://github.com/danielroe/nuxt-vitest) is planned to be merged to provide unit testing capabilities.
7
+ Nuxt offers first-class support for e2e and unit testing of your Nuxt applications.
8
8
 
9
9
  Nuxt Test Utils is currently powering [the tests we use on Nuxt itself](https://github.com/nuxt/nuxt/tree/main/test), as well as tests used throughout the module ecosystem.
10
10
 
package/dist/config.d.mts CHANGED
@@ -2,12 +2,17 @@ import * as vite from 'vite';
2
2
  import { InlineConfig } from 'vite';
3
3
  import { NuxtConfig, Nuxt } from '@nuxt/schema';
4
4
  import { InlineConfig as InlineConfig$1 } from 'vitest';
5
+ import { DotenvOptions } from 'c12';
5
6
 
6
7
  interface GetVitestConfigOptions {
7
8
  nuxt: Nuxt;
8
9
  viteConfig: InlineConfig;
9
10
  }
10
- declare function getVitestConfigFromNuxt(options?: GetVitestConfigOptions, overrides?: NuxtConfig): Promise<InlineConfig & {
11
+ interface LoadNuxtOptions {
12
+ dotenv?: Partial<DotenvOptions>;
13
+ overrides?: Partial<NuxtConfig>;
14
+ }
15
+ declare function getVitestConfigFromNuxt(options?: GetVitestConfigOptions, loadNuxtOptions?: LoadNuxtOptions): Promise<InlineConfig & {
11
16
  test: InlineConfig$1;
12
17
  }>;
13
18
  declare function defineVitestConfig(config?: InlineConfig & {
@@ -22,6 +27,13 @@ declare module 'vitest' {
22
27
  * @default {http://localhost:3000}
23
28
  */
24
29
  url?: string;
30
+ /**
31
+ * You can define how environment options are read when loading the Nuxt configuration.
32
+ */
33
+ dotenv?: Partial<DotenvOptions>;
34
+ /**
35
+ * Configuration that will override the values in your `nuxt.config` file.
36
+ */
25
37
  overrides?: NuxtConfig;
26
38
  /**
27
39
  * The id of the root div to which the app should be mounted. You should also set `app.rootId` to the same value.
package/dist/config.d.ts CHANGED
@@ -2,12 +2,17 @@ import * as vite from 'vite';
2
2
  import { InlineConfig } from 'vite';
3
3
  import { NuxtConfig, Nuxt } from '@nuxt/schema';
4
4
  import { InlineConfig as InlineConfig$1 } from 'vitest';
5
+ import { DotenvOptions } from 'c12';
5
6
 
6
7
  interface GetVitestConfigOptions {
7
8
  nuxt: Nuxt;
8
9
  viteConfig: InlineConfig;
9
10
  }
10
- declare function getVitestConfigFromNuxt(options?: GetVitestConfigOptions, overrides?: NuxtConfig): Promise<InlineConfig & {
11
+ interface LoadNuxtOptions {
12
+ dotenv?: Partial<DotenvOptions>;
13
+ overrides?: Partial<NuxtConfig>;
14
+ }
15
+ declare function getVitestConfigFromNuxt(options?: GetVitestConfigOptions, loadNuxtOptions?: LoadNuxtOptions): Promise<InlineConfig & {
11
16
  test: InlineConfig$1;
12
17
  }>;
13
18
  declare function defineVitestConfig(config?: InlineConfig & {
@@ -22,6 +27,13 @@ declare module 'vitest' {
22
27
  * @default {http://localhost:3000}
23
28
  */
24
29
  url?: string;
30
+ /**
31
+ * You can define how environment options are read when loading the Nuxt configuration.
32
+ */
33
+ dotenv?: Partial<DotenvOptions>;
34
+ /**
35
+ * Configuration that will override the values in your `nuxt.config` file.
36
+ */
25
37
  overrides?: NuxtConfig;
26
38
  /**
27
39
  * The id of the root div to which the app should be mounted. You should also set `app.rootId` to the same value.
package/dist/config.mjs CHANGED
@@ -1,24 +1,61 @@
1
1
  import { defineConfig } from 'vite';
2
+ import { setupDotenv } from 'c12';
2
3
  import { defu } from 'defu';
3
4
  import { createResolver } from '@nuxt/kit';
5
+ import destr from 'destr';
6
+ import { snakeCase } from 'scule';
4
7
 
5
- async function startNuxtAndGetViteConfig(rootDir = process.cwd(), overrides) {
8
+ function getEnv(key, opts) {
9
+ const env = opts.env ?? process.env;
10
+ const envKey = snakeCase(key).toUpperCase();
11
+ return destr(
12
+ env[opts.prefix + envKey] ?? env[opts.altPrefix + envKey]
13
+ );
14
+ }
15
+ function _isObject(input) {
16
+ return typeof input === "object" && !Array.isArray(input);
17
+ }
18
+ function applyEnv(obj, opts, parentKey = "") {
19
+ for (const key in obj) {
20
+ const subKey = parentKey ? `${parentKey}_${key}` : key;
21
+ const envValue = getEnv(subKey, opts);
22
+ if (_isObject(obj[key])) {
23
+ if (_isObject(envValue)) {
24
+ obj[key] = { ...obj[key], ...envValue };
25
+ applyEnv(obj[key], opts, subKey);
26
+ } else if (envValue === void 0) {
27
+ applyEnv(obj[key], opts, subKey);
28
+ } else {
29
+ obj[key] = envValue ?? obj[key];
30
+ }
31
+ } else {
32
+ obj[key] = envValue ?? obj[key];
33
+ }
34
+ }
35
+ return obj;
36
+ }
37
+
38
+ async function startNuxtAndGetViteConfig(rootDir = process.cwd(), options = {}) {
6
39
  const { loadNuxt, buildNuxt } = await import('@nuxt/kit');
7
40
  const nuxt = await loadNuxt({
8
41
  cwd: rootDir,
9
42
  dev: false,
43
+ dotenv: defu(options.dotenv, {
44
+ cwd: rootDir,
45
+ fileName: ".env.test"
46
+ }),
10
47
  overrides: defu(
11
48
  {
12
49
  ssr: false,
13
50
  test: true,
14
51
  modules: ["@nuxt/test-utils/module"]
15
52
  },
16
- overrides
53
+ options.overrides
17
54
  )
18
55
  });
19
56
  if (!nuxt.options._installedModules.find((i) => i?.meta?.name === "@nuxt/test-utils")) {
20
57
  throw new Error(
21
- "Failed to load nuxt-vitest module. You may need to add it to your nuxt.config."
58
+ "Failed to load `@nuxt/test-utils/module`. You may need to add it to your nuxt.config."
22
59
  );
23
60
  }
24
61
  const promise = new Promise((resolve, reject) => {
@@ -36,19 +73,22 @@ async function startNuxtAndGetViteConfig(rootDir = process.cwd(), overrides) {
36
73
  }).finally(() => nuxt.close());
37
74
  return promise;
38
75
  }
39
- async function getVitestConfigFromNuxt(options, overrides) {
40
- var _a;
41
- const { rootDir = process.cwd(), ..._overrides } = overrides || {};
76
+ const excludedPlugins = [
77
+ "nuxt:import-protection",
78
+ "vite-plugin-checker"
79
+ ];
80
+ async function getVitestConfigFromNuxt(options, loadNuxtOptions = {}) {
81
+ const { rootDir = process.cwd(), ..._overrides } = loadNuxtOptions.overrides || {};
42
82
  if (!options) {
43
83
  options = await startNuxtAndGetViteConfig(rootDir, {
44
- test: true,
45
- ..._overrides
84
+ dotenv: loadNuxtOptions.dotenv,
85
+ overrides: {
86
+ test: true,
87
+ ..._overrides
88
+ }
46
89
  });
47
90
  }
48
- (_a = options.viteConfig).plugins || (_a.plugins = []);
49
- options.viteConfig.plugins = options.viteConfig.plugins?.filter(
50
- (p) => p?.name !== "nuxt:import-protection"
51
- );
91
+ options.viteConfig.plugins = (options.viteConfig.plugins || []).filter((p) => !excludedPlugins.includes(p?.name));
52
92
  const resolvedConfig = defu(
53
93
  // overrides
54
94
  {
@@ -58,7 +98,13 @@ async function getVitestConfigFromNuxt(options, overrides) {
58
98
  test: {
59
99
  dir: process.cwd(),
60
100
  environmentOptions: {
61
- nuxtRuntimeConfig: options.nuxt.options.runtimeConfig,
101
+ nuxtRuntimeConfig: applyEnv(structuredClone(options.nuxt.options.runtimeConfig), {
102
+ prefix: "NUXT_",
103
+ env: await setupDotenv(defu(loadNuxtOptions.dotenv, {
104
+ cwd: rootDir,
105
+ fileName: ".env.test"
106
+ }))
107
+ }),
62
108
  nuxtRouteRules: defu(
63
109
  {},
64
110
  options.nuxt.options.routeRules,
@@ -69,20 +115,29 @@ async function getVitestConfigFromNuxt(options, overrides) {
69
115
  ["**/*.nuxt.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}", "nuxt"],
70
116
  ["{test,tests}/nuxt/**.*", "nuxt"]
71
117
  ],
118
+ server: {
119
+ deps: {
120
+ inline: [
121
+ // vite-node defaults
122
+ /\/node_modules\/(.*\/)?(nuxt|nuxt3|nuxt-nightly)\//,
123
+ /^#/,
124
+ // additional deps
125
+ "@nuxt/test-utils",
126
+ "@nuxt/test-utils-nightly",
127
+ "@nuxt/test-utils-edge",
128
+ "vitest-environment-nuxt",
129
+ ...options.nuxt.options.build.transpile.filter(
130
+ (r) => typeof r === "string" || r instanceof RegExp
131
+ )
132
+ ]
133
+ }
134
+ },
72
135
  deps: {
73
- inline: [
74
- // vite-node defaults
75
- /\/node_modules\/(.*\/)?(nuxt|nuxt3|nuxt-nightly)\//,
76
- /^#/,
77
- // additional deps
78
- "@nuxt/test-utils",
79
- "@nuxt/test-utils-nightly",
80
- "@nuxt/test-utils-edge",
81
- "vitest-environment-nuxt",
82
- ...options.nuxt.options.build.transpile.filter(
83
- (r) => typeof r === "string" || r instanceof RegExp
84
- )
85
- ]
136
+ optimizer: {
137
+ web: {
138
+ enabled: false
139
+ }
140
+ }
86
141
  }
87
142
  }
88
143
  },
@@ -134,9 +189,15 @@ function defineVitestConfig(config = {}) {
134
189
  return config;
135
190
  const overrides = config.test?.environmentOptions?.nuxt?.overrides || {};
136
191
  overrides.rootDir = config.test?.environmentOptions?.nuxt?.rootDir;
192
+ if (config.test?.setupFiles && !Array.isArray(config.test.setupFiles)) {
193
+ config.test.setupFiles = [config.test.setupFiles].filter(Boolean);
194
+ }
137
195
  return defu(
138
196
  config,
139
- await getVitestConfigFromNuxt(void 0, overrides)
197
+ await getVitestConfigFromNuxt(void 0, {
198
+ dotenv: config.test?.environmentOptions?.nuxt?.dotenv,
199
+ overrides: structuredClone(overrides)
200
+ })
140
201
  );
141
202
  });
142
203
  }
@@ -37,6 +37,11 @@ interface TestContext {
37
37
  url?: string;
38
38
  serverProcess?: ExecaChildProcess;
39
39
  mockFn?: Function;
40
+ /**
41
+ * Functions to run on the vitest `afterAll` hook.
42
+ * Useful for removing anything created during the test.
43
+ */
44
+ teardown?: (() => void)[];
40
45
  }
41
46
  interface TestHooks {
42
47
  beforeEach: () => void;
@@ -37,6 +37,11 @@ interface TestContext {
37
37
  url?: string;
38
38
  serverProcess?: ExecaChildProcess;
39
39
  mockFn?: Function;
40
+ /**
41
+ * Functions to run on the vitest `afterAll` hook.
42
+ * Useful for removing anything created during the test.
43
+ */
44
+ teardown?: (() => void)[];
40
45
  }
41
46
  interface TestHooks {
42
47
  beforeEach: () => void;
@@ -1,7 +1,7 @@
1
- import { u as useTestContext, a as url, c as createTestContext, s as setTestContext, b as stopServer, d as startServer } from './shared/test-utils-nightly.ddf5bsCK.mjs';
2
- export { $ as $fetch, e as exposeContextToEnv, f as fetch, i as isDev, r as recoverContextFromEnv } from './shared/test-utils-nightly.ddf5bsCK.mjs';
1
+ import { u as useTestContext, a as url, c as createTestContext, s as setTestContext, b as stopServer, d as startServer } from './shared/test-utils-nightly.B1uaYm8K.mjs';
2
+ export { $ as $fetch, e as exposeContextToEnv, f as fetch, i as isDev, r as recoverContextFromEnv } from './shared/test-utils-nightly.B1uaYm8K.mjs';
3
3
  import { consola } from 'consola';
4
- import { promises, existsSync } from 'node:fs';
4
+ import { existsSync, promises } from 'node:fs';
5
5
  import { resolve } from 'node:path';
6
6
  import { defu } from 'defu';
7
7
  import * as _kit from '@nuxt/kit';
@@ -83,12 +83,12 @@ async function loadFixture() {
83
83
  ctx.options.rootDir = resolveRootDir();
84
84
  if (!ctx.options.dev) {
85
85
  const randomId = Math.random().toString(36).slice(2, 8);
86
- const buildDir = ctx.options.buildDir || resolve(ctx.options.rootDir, ".nuxt", randomId);
86
+ const buildDir2 = ctx.options.buildDir || resolve(ctx.options.rootDir, ".nuxt", "test", randomId);
87
87
  ctx.options.nuxtConfig = defu(ctx.options.nuxtConfig, {
88
- buildDir,
88
+ buildDir: buildDir2,
89
89
  nitro: {
90
90
  output: {
91
- dir: resolve(buildDir, "output")
91
+ dir: resolve(buildDir2, "output")
92
92
  }
93
93
  }
94
94
  });
@@ -99,7 +99,12 @@ async function loadFixture() {
99
99
  overrides: ctx.options.nuxtConfig,
100
100
  configFile: ctx.options.configFile
101
101
  });
102
- await promises.mkdir(ctx.nuxt.options.buildDir, { recursive: true });
102
+ const buildDir = ctx.nuxt.options.buildDir;
103
+ if (!existsSync(buildDir)) {
104
+ await promises.mkdir(buildDir, { recursive: true });
105
+ ctx.teardown = ctx.teardown || [];
106
+ ctx.teardown.push(() => promises.rm(buildDir, { recursive: true, force: true }));
107
+ }
103
108
  }
104
109
  async function buildFixture() {
105
110
  const ctx = useTestContext();
@@ -151,6 +156,7 @@ function createTest(options) {
151
156
  if (ctx.browser) {
152
157
  await ctx.browser.close();
153
158
  }
159
+ await Promise.all((ctx.teardown || []).map((fn) => fn()));
154
160
  };
155
161
  const setup2 = async () => {
156
162
  if (ctx.options.fixture) {
@@ -1,6 +1,6 @@
1
1
  import { resolve } from 'pathe';
2
2
  import { stringifyQuery } from 'ufo';
3
- import { $ as $fetch, u as useTestContext } from './shared/test-utils-nightly.ddf5bsCK.mjs';
3
+ import { $ as $fetch, u as useTestContext } from './shared/test-utils-nightly.B1uaYm8K.mjs';
4
4
  import 'execa';
5
5
  import 'get-port-please';
6
6
  import 'ofetch';
package/dist/module.mjs CHANGED
@@ -12,6 +12,10 @@ import MagicString from 'magic-string';
12
12
  import { normalize, resolve } from 'node:path';
13
13
  import { createUnplugin } from 'unplugin';
14
14
  import { readFileSync } from 'node:fs';
15
+ import { extname, join, dirname } from 'pathe';
16
+ import 'c12';
17
+ import 'destr';
18
+ import 'scule';
15
19
 
16
20
  const PLUGIN_NAME$1 = "nuxt:vitest:mock-transform";
17
21
  const HELPER_MOCK_IMPORT = "mockNuxtImport";
@@ -224,7 +228,7 @@ const createMockPlugin = (ctx) => createUnplugin(() => {
224
228
  resolvedFirstSetupFile = await resolvePath(normalize(resolve(firstSetupFile)));
225
229
  }
226
230
  const plugins = config.plugins || [];
227
- const vitestPlugins = plugins.filter((p) => p.name === "vite:mocks" || p.name.startsWith("vitest:"));
231
+ const vitestPlugins = plugins.filter((p) => (p.name === "vite:mocks" || p.name.startsWith("vitest:")) && (p.enforce || p.order) === "post");
228
232
  const lastNuxt = findLastIndex(
229
233
  plugins,
230
234
  (i) => i.name?.startsWith("nuxt:")
@@ -300,18 +304,20 @@ function setupImportMocking() {
300
304
  }
301
305
 
302
306
  const PLUGIN_NAME = "nuxt:vitest:nuxt-root-stub";
307
+ const STUB_ID = "nuxt-vitest-app-entry";
303
308
  const NuxtRootStubPlugin = createUnplugin((options) => {
309
+ const STUB_ID_WITH_EXT = STUB_ID + extname(options.entry);
304
310
  return {
305
311
  name: PLUGIN_NAME,
306
312
  enforce: "pre",
307
313
  vite: {
308
- async resolveId(id) {
309
- if (id.endsWith("nuxt-vitest-app-entry")) {
310
- return id;
314
+ async resolveId(id, importer) {
315
+ if (id.endsWith(STUB_ID) || id.endsWith(STUB_ID_WITH_EXT)) {
316
+ return importer?.endsWith("index.html") ? id : join(dirname(options.entry), STUB_ID_WITH_EXT);
311
317
  }
312
318
  },
313
319
  async load(id) {
314
- if (id.endsWith("nuxt-vitest-app-entry")) {
320
+ if (id.endsWith(STUB_ID) || id.endsWith(STUB_ID_WITH_EXT)) {
315
321
  const entryContents = readFileSync(options.entry, "utf-8");
316
322
  return entryContents.replace("#build/root-component.mjs", options.rootStubPath);
317
323
  }
@@ -320,7 +326,7 @@ const NuxtRootStubPlugin = createUnplugin((options) => {
320
326
  };
321
327
  });
322
328
 
323
- const vitePluginBlocklist = ["vite-plugin-vue-inspector", "vite-plugin-inspect"];
329
+ const vitePluginBlocklist = ["vite-plugin-vue-inspector", "vite-plugin-vue-inspector:post", "vite-plugin-inspect"];
324
330
  const module = defineNuxtModule({
325
331
  meta: {
326
332
  name: "@nuxt/test-utils",
@@ -341,9 +347,6 @@ const module = defineNuxtModule({
341
347
  }));
342
348
  if (!nuxt.options.dev)
343
349
  return;
344
- if (nuxt.options.test && nuxt.options.app.rootId === "__nuxt") {
345
- nuxt.options.app.rootId = "nuxt-test";
346
- }
347
350
  if (process.env.TEST || process.env.VITE_TEST)
348
351
  return;
349
352
  const rawViteConfigPromise = new Promise((resolve) => {
@@ -354,8 +357,6 @@ const module = defineNuxtModule({
354
357
  });
355
358
  });
356
359
  });
357
- const PORT = await getPort({ port: 15555 });
358
- const URL = `http://localhost:${PORT}/__vitest__/`;
359
360
  let loaded = false;
360
361
  let promise;
361
362
  let ctx = void 0;
@@ -363,6 +364,7 @@ const module = defineNuxtModule({
363
364
  const updateTabs = debounce(() => {
364
365
  nuxt.callHook("devtools:customTabs:refresh");
365
366
  }, 100);
367
+ let URL;
366
368
  async function start() {
367
369
  const rawViteConfig = mergeConfig({}, await rawViteConfigPromise);
368
370
  const viteConfig = await getVitestConfigFromNuxt({ nuxt, viteConfig: defu({ test: options.vitestConfig }, rawViteConfig) });
@@ -385,6 +387,9 @@ const module = defineNuxtModule({
385
387
  }
386
388
  };
387
389
  const watchMode = !process.env.NUXT_VITEST_DEV_TEST && !isCI;
390
+ const PORT = await getPort({ port: 15555 });
391
+ const PROTOCOL = nuxt.options.devServer.https ? "https" : "http";
392
+ URL = `${PROTOCOL}://localhost:${PORT}/__vitest__/`;
388
393
  const overrides = watchMode ? {
389
394
  passWithNoTests: true,
390
395
  reporters: options.logToConsole ? [
@@ -403,10 +408,10 @@ const module = defineNuxtModule({
403
408
  promise2.catch(() => process.exit(1));
404
409
  if (watchMode) {
405
410
  logger.info(`Vitest UI starting on ${URL}`);
411
+ nuxt.hook("close", () => promise2.then((v) => v?.close()));
406
412
  await new Promise((resolve) => setTimeout(resolve, 1e3));
407
413
  } else {
408
- promise2.then((v) => v?.close()).then(() => process.exit());
409
- promise2.catch(() => process.exit(1));
414
+ promise2.then((v) => nuxt.close().then(() => v?.close()).then(() => process.exit()));
410
415
  }
411
416
  loaded = true;
412
417
  }
@@ -1,5 +1,6 @@
1
1
  if (typeof window !== "undefined" && // @ts-expect-error undefined property
2
2
  window.__NUXT_VITEST_ENVIRONMENT__) {
3
+ const { useRouter } = await import("#app/composables/router");
3
4
  await import("#app/nuxt-vitest-app-entry").then((r) => r.default());
4
5
  const nuxtApp = useNuxtApp();
5
6
  await nuxtApp.callHook("page:finish");
@@ -1,5 +1,5 @@
1
1
  import * as _kit from "@nuxt/kit";
2
- import { createTest, exposeContextToEnv } from "@nuxt/test-utils";
2
+ import { createTest, exposeContextToEnv } from "@nuxt/test-utils/e2e";
3
3
  const kit = _kit.default || _kit;
4
4
  const options = JSON.parse(process.env.NUXT_TEST_OPTIONS || "{}");
5
5
  const hooks = createTest(options);
@@ -13,7 +13,7 @@ type OptionalFunction<T> = T | (() => Awaitable<T>);
13
13
  * @param options - factory function that returns the mocked data or an object containing both the `handler` and the `method` properties.
14
14
  * @example
15
15
  * ```ts
16
- * import { registerEndpoint } from '@nuxt/test-utils/runtime-utils'
16
+ * import { registerEndpoint } from '@nuxt/test-utils/runtime'
17
17
  *
18
18
  * registerEndpoint("/test/", () => {
19
19
  * test: "test-field"
@@ -31,7 +31,7 @@ declare function registerEndpoint(url: string, options: EventHandler | {
31
31
  * @param _factory - factory function that returns mocked import.
32
32
  * @example
33
33
  * ```ts
34
- * import { mockNuxtImport } from '@nuxt/test-utils/runtime-utils'
34
+ * import { mockNuxtImport } from '@nuxt/test-utils/runtime'
35
35
  *
36
36
  * mockNuxtImport('useStorage', () => {
37
37
  * return () => {
@@ -48,7 +48,7 @@ declare function mockNuxtImport<T = any>(_name: string, _factory: () => T | Prom
48
48
  * @param setup - factory function that returns the mocked component.
49
49
  * @example
50
50
  * ```ts
51
- * import { mockComponent } from '@nuxt/test-utils/runtime-utils'
51
+ * import { mockComponent } from '@nuxt/test-utils/runtime'
52
52
  *
53
53
  * mockComponent('MyComponent', {
54
54
  * props: {
@@ -123,7 +123,7 @@ type RenderOptions = RenderOptions$1 & {
123
123
  *
124
124
  * ```ts
125
125
  * // tests/components/SomeComponents.nuxt.spec.ts
126
- * import { renderSuspended } from '@nuxt/test-utils/runtime-utils'
126
+ * import { renderSuspended } from '@nuxt/test-utils/runtime'
127
127
  *
128
128
  * it('can render some component', async () => {
129
129
  * const { html } = await renderSuspended(SomeComponent)
@@ -134,7 +134,7 @@ type RenderOptions = RenderOptions$1 & {
134
134
  * })
135
135
  *
136
136
  * // tests/App.nuxt.spec.ts
137
- * import { renderSuspended } from '@nuxt/test-utils/runtime-utils'
137
+ * import { renderSuspended } from '@nuxt/test-utils/runtime'
138
138
  * import { screen } from '@testing-library/vue'
139
139
  *
140
140
  * it('can also mount an app', async () => {
@@ -13,7 +13,7 @@ type OptionalFunction<T> = T | (() => Awaitable<T>);
13
13
  * @param options - factory function that returns the mocked data or an object containing both the `handler` and the `method` properties.
14
14
  * @example
15
15
  * ```ts
16
- * import { registerEndpoint } from '@nuxt/test-utils/runtime-utils'
16
+ * import { registerEndpoint } from '@nuxt/test-utils/runtime'
17
17
  *
18
18
  * registerEndpoint("/test/", () => {
19
19
  * test: "test-field"
@@ -31,7 +31,7 @@ declare function registerEndpoint(url: string, options: EventHandler | {
31
31
  * @param _factory - factory function that returns mocked import.
32
32
  * @example
33
33
  * ```ts
34
- * import { mockNuxtImport } from '@nuxt/test-utils/runtime-utils'
34
+ * import { mockNuxtImport } from '@nuxt/test-utils/runtime'
35
35
  *
36
36
  * mockNuxtImport('useStorage', () => {
37
37
  * return () => {
@@ -48,7 +48,7 @@ declare function mockNuxtImport<T = any>(_name: string, _factory: () => T | Prom
48
48
  * @param setup - factory function that returns the mocked component.
49
49
  * @example
50
50
  * ```ts
51
- * import { mockComponent } from '@nuxt/test-utils/runtime-utils'
51
+ * import { mockComponent } from '@nuxt/test-utils/runtime'
52
52
  *
53
53
  * mockComponent('MyComponent', {
54
54
  * props: {
@@ -123,7 +123,7 @@ type RenderOptions = RenderOptions$1 & {
123
123
  *
124
124
  * ```ts
125
125
  * // tests/components/SomeComponents.nuxt.spec.ts
126
- * import { renderSuspended } from '@nuxt/test-utils/runtime-utils'
126
+ * import { renderSuspended } from '@nuxt/test-utils/runtime'
127
127
  *
128
128
  * it('can render some component', async () => {
129
129
  * const { html } = await renderSuspended(SomeComponent)
@@ -134,7 +134,7 @@ type RenderOptions = RenderOptions$1 & {
134
134
  * })
135
135
  *
136
136
  * // tests/App.nuxt.spec.ts
137
- * import { renderSuspended } from '@nuxt/test-utils/runtime-utils'
137
+ * import { renderSuspended } from '@nuxt/test-utils/runtime'
138
138
  * import { screen } from '@testing-library/vue'
139
139
  *
140
140
  * it('can also mount an app', async () => {
@@ -102,19 +102,21 @@ async function mountSuspended(component, options) {
102
102
  },
103
103
  {
104
104
  default: () => h$1({
105
+ name: "MountSuspendedHelper",
105
106
  async setup() {
106
107
  const router = useRouter();
107
108
  await router.replace(route);
108
109
  const clonedComponent = {
110
+ name: "MountSuspendedComponent",
109
111
  ...component,
110
- render: render ? (_ctx, ...args) => {
111
- for (const key in _ctx) {
112
+ render: render ? function(_ctx, ...args) {
113
+ for (const key in props || {}) {
112
114
  renderContext[key] = _ctx[key];
113
115
  }
114
- return render.apply(_ctx, [
115
- renderContext,
116
- ...args
117
- ]);
116
+ for (const key in setupState || {}) {
117
+ renderContext[key] = setupState[key];
118
+ }
119
+ return render.call(this, renderContext, ...args);
118
120
  } : void 0,
119
121
  setup: setup ? (props2) => wrappedSetup(props2, setupContext) : void 0
120
122
  };
@@ -124,16 +126,24 @@ async function mountSuspended(component, options) {
124
126
  }
125
127
  )
126
128
  },
127
- defu(_options, {
128
- slots,
129
- global: {
130
- config: {
131
- globalProperties: vueApp.config.globalProperties
132
- },
133
- provide: vueApp._context.provides,
134
- components: { RouterLink }
129
+ defu(
130
+ _options,
131
+ {
132
+ slots,
133
+ global: {
134
+ config: {
135
+ globalProperties: vueApp.config.globalProperties
136
+ },
137
+ provide: vueApp._context.provides,
138
+ stubs: {
139
+ Suspense: false,
140
+ MountSuspendedHelper: false,
141
+ [typeof component.name === "string" ? component.name : "MountSuspendedComponent"]: false
142
+ },
143
+ components: { RouterLink }
144
+ }
135
145
  }
136
- })
146
+ )
137
147
  );
138
148
  }
139
149
  );
@@ -151,6 +161,7 @@ async function renderSuspended(component, options) {
151
161
  const { render: renderFromTestingLibrary } = await import('@testing-library/vue');
152
162
  const { vueApp } = globalThis.__unctx__.get("nuxt-app").tryUse();
153
163
  const { render, setup } = component;
164
+ document.querySelector(`#${WRAPPER_EL_ID}`)?.remove();
154
165
  let setupContext;
155
166
  return new Promise((resolve) => {
156
167
  const utils = renderFromTestingLibrary(
@@ -18,8 +18,7 @@ function createTestContext(options) {
18
18
  server: true,
19
19
  build: options.browser !== false || options.server !== false,
20
20
  nuxtConfig: {},
21
- // TODO: auto detect based on process.env
22
- runner: "vitest",
21
+ runner: process.env.VITEST === "true" ? "vitest" : "jest",
23
22
  browserOptions: {
24
23
  type: "chromium"
25
24
  }
package/e2e.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './dist/e2e'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuxt/test-utils-nightly",
3
- "version": "4.0.0-1701501480.7490334",
3
+ "version": "4.0.0-1702910449.8cf01bd",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/nuxt/test-utils.git"
@@ -8,21 +8,23 @@
8
8
  "description": "Test utilities for Nuxt",
9
9
  "license": "MIT",
10
10
  "type": "module",
11
- "types": "./dist/index.d.ts",
11
+ "types": "./dist/e2e.d.ts",
12
12
  "exports": {
13
- ".": "./dist/index.mjs",
13
+ ".": "./dist/e2e.mjs",
14
14
  "./config": "./dist/config.mjs",
15
+ "./e2e": "./dist/e2e.mjs",
15
16
  "./experimental": "./dist/experimental.mjs",
16
17
  "./module": "./dist/module.mjs",
17
- "./runtime-utils": "./dist/runtime-utils.mjs",
18
+ "./runtime": "./dist/runtime-utils/index.mjs",
18
19
  "./vitest-environment": "./dist/vitest-environment.mjs"
19
20
  },
20
21
  "files": [
21
22
  "dist",
22
23
  "config.d.ts",
24
+ "e2e.d.ts",
23
25
  "experimental.d.ts",
24
26
  "module.d.ts",
25
- "runtime-utils.d.ts",
27
+ "runtime.d.ts",
26
28
  "vitest-environment.d.ts"
27
29
  ],
28
30
  "scripts": {
@@ -38,8 +40,10 @@
38
40
  "dependencies": {
39
41
  "@nuxt/kit": "^3.8.2",
40
42
  "@nuxt/schema": "^3.8.2",
43
+ "c12": "^1.5.1",
41
44
  "consola": "^3.2.3",
42
45
  "defu": "^6.1.3",
46
+ "destr": "^2.0.2",
43
47
  "estree-walker": "^3.0.3",
44
48
  "execa": "^8.0.1",
45
49
  "fake-indexeddb": "^5.0.1",
@@ -51,50 +55,54 @@
51
55
  "pathe": "^1.1.1",
52
56
  "perfect-debounce": "^1.0.0",
53
57
  "radix3": "^1.1.0",
58
+ "scule": "^1.1.1",
54
59
  "std-env": "^3.6.0",
55
60
  "ufo": "^1.3.2",
56
61
  "unenv": "^1.8.0",
57
62
  "unplugin": "^1.5.1",
58
- "vitest-environment-nuxt": "0.12.0"
63
+ "vitest-environment-nuxt": "1.0.0-alpha.1"
59
64
  },
60
65
  "devDependencies": {
61
66
  "@jest/globals": "29.7.0",
62
- "@nuxt/devtools": "1.0.4",
67
+ "@nuxt/devtools": "1.0.6",
63
68
  "@nuxt/eslint-config": "0.2.0",
64
69
  "@nuxt/module-builder": "0.5.4",
65
70
  "@testing-library/vue": "8.0.1",
66
71
  "@types/estree": "1.0.5",
67
72
  "@types/jsdom": "21.1.6",
68
- "@vitest/ui": "0.33.0",
73
+ "@types/semver": "7.5.6",
74
+ "@vitest/ui": "1.0.4",
69
75
  "@vue/test-utils": "2.4.3",
70
76
  "changelogen": "0.5.5",
71
- "eslint": "8.55.0",
72
- "eslint-plugin-import": "2.29.0",
73
- "eslint-plugin-jsdoc": "46.9.0",
77
+ "eslint": "8.56.0",
78
+ "eslint-plugin-import": "2.29.1",
79
+ "eslint-plugin-jsdoc": "46.9.1",
74
80
  "eslint-plugin-no-only-tests": "3.1.0",
75
81
  "eslint-plugin-unicorn": "49.0.0",
76
82
  "h3": "1.9.0",
83
+ "jiti": "1.21.0",
77
84
  "nuxt": "3.8.2",
78
85
  "playwright-core": "1.40.1",
79
- "rollup": "4.6.1",
86
+ "rollup": "4.9.1",
87
+ "semver": "7.5.4",
80
88
  "unbuild": "latest",
81
- "unimport": "3.6.0",
82
- "vite": "5.0.4",
83
- "vitest": "0.33.0",
89
+ "unimport": "3.6.1",
90
+ "vite": "5.0.10",
91
+ "vitest": "1.0.4",
84
92
  "vue-router": "4.2.5",
85
- "vue-tsc": "1.8.24"
93
+ "vue-tsc": "1.8.25"
86
94
  },
87
95
  "peerDependencies": {
88
96
  "@jest/globals": "^29.5.0",
89
97
  "@testing-library/vue": "^7.0.0 || ^8.0.1",
90
- "@vitest/ui": "0.33.0",
98
+ "@vitest/ui": "^0.34.6 || ^1.0.0",
91
99
  "@vue/test-utils": "^2.4.2",
92
100
  "h3": "*",
93
101
  "happy-dom": "^9.10.9 || ^10.0.0 || ^11.0.0 || ^12.0.0",
94
102
  "jsdom": "^22.0.0 || ^23.0.0",
95
103
  "playwright-core": "^1.34.3",
96
104
  "vite": "*",
97
- "vitest": "^0.24.5 || ^0.26.0 || ^0.27.0 || ^0.28.0 || ^0.29.0 || ^0.30.0 || ^0.33.0",
105
+ "vitest": "^0.34.6 || ^1.0.0",
98
106
  "vue": "^3.3.4",
99
107
  "vue-router": "^4.0.0"
100
108
  },
@@ -126,12 +134,11 @@
126
134
  },
127
135
  "resolutions": {
128
136
  "@nuxt/test-utils": "workspace:*",
129
- "vitest-environment-nuxt": "workspace:*",
130
- "rollup": "4.6.1",
131
- "vite": "5.0.4"
137
+ "rollup": "4.9.1",
138
+ "vite": "5.0.10"
132
139
  },
133
140
  "engines": {
134
141
  "node": "^14.18.0 || >=16.10.0"
135
142
  },
136
- "packageManager": "pnpm@8.11.0"
143
+ "packageManager": "pnpm@8.12.1"
137
144
  }
package/runtime.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './dist/runtime-utils/index.mjs'
@@ -1 +0,0 @@
1
- export * from './dist/runtime-utils'