@nuxt/test-utils-nightly 3.21.0-20251031-123045-c452751 → 3.21.0-20251204-130449-b6179fd

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/dist/module.mjs CHANGED
@@ -10,7 +10,7 @@ import { walk } from 'estree-walker';
10
10
  import MagicString from 'magic-string';
11
11
  import { createUnplugin } from 'unplugin';
12
12
  import { readFileSync } from 'node:fs';
13
- import { extname, join, dirname } from 'pathe';
13
+ import { extname, join, dirname, relative } from 'pathe';
14
14
  import 'node:process';
15
15
  import 'vite';
16
16
  import 'c12';
@@ -67,16 +67,16 @@ const createMockPlugin = (ctx) => createUnplugin(() => {
67
67
  startOf(node)
68
68
  );
69
69
  }
70
- const importName = node.arguments[0];
71
- if (!isLiteral(importName) || typeof importName.value !== "string") {
70
+ const importTarget = node.arguments[0];
71
+ const name = isLiteral(importTarget) ? importTarget.value : isIdentifier(importTarget) ? importTarget.name : void 0;
72
+ if (typeof name !== "string") {
72
73
  return this.error(
73
74
  new Error(
74
- `The first argument of ${HELPER_MOCK_IMPORT}() must be a string literal`
75
+ `The first argument of ${HELPER_MOCK_IMPORT}() must be a string literal or mocked target`
75
76
  ),
76
- startOf(importName)
77
+ startOf(importTarget)
77
78
  );
78
79
  }
79
- const name = importName.value;
80
80
  const importItem = ctx.imports.find((_) => name === (_.as || _.name));
81
81
  if (!importItem) {
82
82
  console.log({ imports: ctx.imports });
@@ -317,7 +317,7 @@ const NuxtRootStubPlugin = createUnplugin((options) => {
317
317
  });
318
318
 
319
319
  const vitePluginBlocklist = ["vite-plugin-vue-inspector", "vite-plugin-vue-inspector:post", "vite-plugin-inspect", "nuxt:type-check"];
320
- const module = defineNuxtModule({
320
+ const module$1 = defineNuxtModule({
321
321
  meta: {
322
322
  name: "@nuxt/test-utils",
323
323
  configKey: "testUtils"
@@ -339,8 +339,15 @@ const module = defineNuxtModule({
339
339
  nuxt.options.vite.define ||= {};
340
340
  nuxt.options.vite.define["import.meta.vitest"] = "undefined";
341
341
  }
342
- nuxt.hook("prepare:types", ({ references }) => {
343
- references.push({ types: "vitest/import-meta" });
342
+ nuxt.hook("prepare:types", (ctx2) => {
343
+ ctx2.references.push({ types: "vitest/import-meta" });
344
+ if (ctx2.nodeTsConfig) {
345
+ ctx2.nodeTsConfig.include ||= [];
346
+ ctx2.nodeTsConfig.include.push(relative(nuxt.options.buildDir, join(nuxt.options.rootDir, "vitest.config.*")));
347
+ if (nuxt.options.workspaceDir !== nuxt.options.rootDir) {
348
+ ctx2.nodeTsConfig.include.push(relative(nuxt.options.buildDir, join(nuxt.options.workspaceDir, "vitest.config.*")));
349
+ }
350
+ }
344
351
  });
345
352
  if (!nuxt.options.dev) return;
346
353
  if (process.env.TEST || process.env.VITE_TEST) return;
@@ -461,4 +468,4 @@ function toArray(value) {
461
468
  return Array.isArray(value) ? value : [value];
462
469
  }
463
470
 
464
- export { module as default };
471
+ export { module$1 as default };
@@ -2,8 +2,7 @@ import { EventHandler, HTTPMethod } from 'h3';
2
2
  import { SetupContext, RenderFunction, ComputedOptions, MethodOptions, ComponentOptionsMixin, EmitsOptions, ComponentInjectOptions, ComponentOptionsWithoutProps, ComponentOptionsWithArrayProps, ComponentPropsOptions, ComponentOptionsWithObjectProps } from 'vue';
3
3
  import { ComponentMountingOptions, mount } from '@vue/test-utils';
4
4
  import { RouteLocationRaw } from 'vue-router';
5
- import * as _testing_library_vue from '@testing-library/vue';
6
- import { RenderOptions as RenderOptions$1 } from '@testing-library/vue';
5
+ import { RenderOptions, RenderResult } from '@testing-library/vue';
7
6
 
8
7
  type Awaitable<T> = T | Promise<T>;
9
8
  type OptionalFunction<T> = T | (() => Awaitable<T>);
@@ -37,7 +36,7 @@ declare function registerEndpoint(url: string, options: EventHandler | {
37
36
  }): () => void;
38
37
  /**
39
38
  * `mockNuxtImport` allows you to mock Nuxt's auto import functionality.
40
- * @param _name - name of an import to mock.
39
+ * @param _target - name of an import to mock or mocked target.
41
40
  * @param _factory - factory function that returns mocked import.
42
41
  * @example
43
42
  * ```ts
@@ -48,10 +47,17 @@ declare function registerEndpoint(url: string, options: EventHandler | {
48
47
  * return { value: 'mocked storage' }
49
48
  * }
50
49
  * })
50
+ *
51
+ * // With mocked target
52
+ * mockNuxtImport(useStorage, () => {
53
+ * return () => {
54
+ * return { value: 'mocked storage' }
55
+ * }
56
+ * })
51
57
  * ```
52
58
  * @see https://nuxt.com/docs/getting-started/testing#mocknuxtimport
53
59
  */
54
- declare function mockNuxtImport<T = unknown>(_name: string, _factory: () => T | Promise<T>): void;
60
+ declare function mockNuxtImport<T = unknown>(_target: string | T, _factory: () => T | Promise<T>): void;
55
61
  /**
56
62
  * `mockComponent` allows you to mock Nuxt's component.
57
63
  * @param path - component name in PascalCase, or the relative path of the component.
@@ -93,6 +99,9 @@ type MountSuspendedOptions<T> = ComponentMountingOptions<T> & {
93
99
  route?: RouteLocationRaw;
94
100
  scoped?: boolean;
95
101
  };
102
+ type MountSuspendedResult<T> = ReturnType<typeof mount<T>> & {
103
+ setupState: SetupState$1;
104
+ };
96
105
  type SetupState$1 = Record<string, any>;
97
106
  /**
98
107
  * `mountSuspended` allows you to mount any vue component within the Nuxt environment, allowing async setup and access to injections from your Nuxt plugins. For example:
@@ -120,16 +129,17 @@ type SetupState$1 = Record<string, any>;
120
129
  * @param component the component to be tested
121
130
  * @param options optional options to set up your component
122
131
  */
123
- declare function mountSuspended<T>(component: T, options?: MountSuspendedOptions<T>): Promise<ReturnType<typeof mount<T>> & {
124
- setupState: SetupState$1;
125
- }>;
132
+ declare function mountSuspended<T>(component: T, options?: MountSuspendedOptions<T>): Promise<MountSuspendedResult<T>>;
126
133
  declare global {
127
134
  var __cleanup: Array<() => void> | undefined;
128
135
  }
129
136
 
130
- type RenderOptions<C = unknown> = RenderOptions$1<C> & {
137
+ type RenderSuspendeOptions<T> = RenderOptions<T> & {
131
138
  route?: RouteLocationRaw;
132
139
  };
140
+ type RenderSuspendeResult = RenderResult & {
141
+ setupState: SetupState;
142
+ };
133
143
  type SetupState = Record<string, any>;
134
144
  /**
135
145
  * `renderSuspended` allows you to mount any vue component within the Nuxt environment, allowing async setup and access to injections from your Nuxt plugins.
@@ -161,9 +171,7 @@ type SetupState = Record<string, any>;
161
171
  * @param component the component to be tested
162
172
  * @param options optional options to set up your component
163
173
  */
164
- declare function renderSuspended<T>(component: T, options?: RenderOptions<T>): Promise<_testing_library_vue.RenderResult & {
165
- setupState: SetupState;
166
- }>;
174
+ declare function renderSuspended<T>(component: T, options?: RenderSuspendeOptions<T>): Promise<RenderSuspendeResult>;
167
175
  declare global {
168
176
  interface Window {
169
177
  __cleanup?: Array<() => void>;
@@ -1,6 +1,6 @@
1
1
  import { defineEventHandler } from 'h3';
2
2
  import { mount } from '@vue/test-utils';
3
- import { reactive, h as h$1, Suspense, nextTick, effectScope, unref, isReadonly, getCurrentInstance, isRef, defineComponent as defineComponent$1 } from 'vue';
3
+ import { reactive, h as h$1, Suspense, nextTick, getCurrentInstance, effectScope, defineComponent as defineComponent$1 } from 'vue';
4
4
  import { defu } from 'defu';
5
5
  import { defineComponent, useRouter, h, tryUseNuxtApp } from '#imports';
6
6
  import NuxtRoot from '#build/root-component.mjs';
@@ -43,7 +43,7 @@ function registerEndpoint(url, options) {
43
43
  }
44
44
  };
45
45
  }
46
- function mockNuxtImport(_name, _factory) {
46
+ function mockNuxtImport(_target, _factory) {
47
47
  throw new Error(
48
48
  "mockNuxtImport() is a macro and it did not get transpiled. This may be an internal bug of @nuxt/test-utils."
49
49
  );
@@ -100,32 +100,27 @@ async function mountSuspended(component, options) {
100
100
  cleanupFunction();
101
101
  }
102
102
  const vueApp = tryUseNuxtApp()?.vueApp || globalThis.__unctx__.get("nuxt-app").tryUse().vueApp;
103
- const { render, setup, data, computed, methods, ...componentRest } = component;
103
+ const { render, setup, ...componentRest } = component;
104
+ let wrappedInstance = null;
104
105
  let setupContext;
105
106
  let setupState;
106
107
  const setProps = reactive({});
107
- let interceptedEmit = null;
108
- function getInterceptedEmitFunction(emit) {
109
- if (emit !== interceptedEmit) {
110
- interceptedEmit = interceptedEmit ?? ((event, ...args) => {
111
- emit(event, ...args);
112
- setupContext.emit(event, ...args);
113
- });
108
+ function patchInstanceAppContext() {
109
+ const app = getCurrentInstance()?.appContext.app;
110
+ if (!app) return;
111
+ for (const [key, value] of Object.entries(vueApp)) {
112
+ if (key in app) continue;
113
+ app[key] = value;
114
114
  }
115
- return interceptedEmit;
116
115
  }
117
- function interceptEmitOnCurrentInstance() {
116
+ let componentScope = null;
117
+ const wrappedSetup = async (props2, setupContext2, instanceContext) => {
118
118
  const currentInstance = getCurrentInstance();
119
- if (!currentInstance) {
120
- return;
119
+ if (currentInstance) {
120
+ currentInstance.emit = (event, ...args) => {
121
+ setupContext2.emit(event, ...args);
122
+ };
121
123
  }
122
- currentInstance.emit = getInterceptedEmitFunction(currentInstance.emit);
123
- }
124
- let passedProps;
125
- let componentScope = null;
126
- const wrappedSetup = async (props2, setupContext2) => {
127
- interceptEmitOnCurrentInstance();
128
- passedProps = props2;
129
124
  if (setup) {
130
125
  let result;
131
126
  if (options?.scoped) {
@@ -140,6 +135,9 @@ async function mountSuspended(component, options) {
140
135
  } else {
141
136
  result = await setup(props2, setupContext2);
142
137
  }
138
+ if (wrappedInstance?.exposed) {
139
+ instanceContext.expose(wrappedInstance.exposed);
140
+ }
143
141
  setupState = result && typeof result === "object" ? result : {};
144
142
  return result;
145
143
  }
@@ -149,7 +147,10 @@ async function mountSuspended(component, options) {
149
147
  const vm = mount(
150
148
  {
151
149
  __cssModules: componentRest.__cssModules,
150
+ inheritAttrs: false,
152
151
  setup: (props2, ctx) => {
152
+ patchInstanceAppContext();
153
+ wrappedInstance = getCurrentInstance();
153
154
  setupContext = ctx;
154
155
  if (options?.scoped) {
155
156
  const scope = effectScope();
@@ -170,7 +171,7 @@ async function mountSuspended(component, options) {
170
171
  });
171
172
  }
172
173
  },
173
- render: (renderContext) => h$1(
174
+ render: () => h$1(
174
175
  Suspense,
175
176
  {
176
177
  onResolve: () => nextTick().then(() => {
@@ -188,56 +189,12 @@ async function mountSuspended(component, options) {
188
189
  const router = useRouter();
189
190
  await router.replace(route);
190
191
  const clonedComponent = {
191
- name: "MountSuspendedComponent",
192
+ components: {},
192
193
  ...component,
193
- render: render ? function(_ctx, ...args) {
194
- interceptEmitOnCurrentInstance();
195
- if (data && typeof data === "function") {
196
- const dataObject = data();
197
- for (const key in dataObject) {
198
- renderContext[key] = dataObject[key];
199
- }
200
- }
201
- for (const key in setupState || {}) {
202
- const warn = console.warn;
203
- console.warn = () => {
204
- };
205
- try {
206
- renderContext[key] = isReadonly(setupState[key]) ? unref(setupState[key]) : setupState[key];
207
- } catch {
208
- } finally {
209
- console.warn = warn;
210
- }
211
- if (key === "props") {
212
- renderContext[key] = cloneProps$1(renderContext[key]);
213
- }
214
- }
215
- const propsContext = "props" in renderContext ? renderContext.props : renderContext;
216
- for (const key in props || {}) {
217
- propsContext[key] = _ctx[key];
218
- }
219
- for (const key in passedProps || {}) {
220
- propsContext[key] = passedProps[key];
221
- }
222
- if (methods && typeof methods === "object") {
223
- for (const [key, value] of Object.entries(methods)) {
224
- renderContext[key] = value.bind(renderContext);
225
- }
226
- }
227
- if (computed && typeof computed === "object") {
228
- for (const [key, value] of Object.entries(computed)) {
229
- if ("get" in value) {
230
- renderContext[key] = value.get.call(renderContext);
231
- } else {
232
- renderContext[key] = value.call(renderContext);
233
- }
234
- }
235
- }
236
- return render.call(this, renderContext, ...args);
237
- } : void 0,
238
- setup: (props2) => wrappedSetup(props2, setupContext)
194
+ name: "MountSuspendedComponent",
195
+ setup: (props2, ctx) => wrappedSetup(props2, setupContext, ctx)
239
196
  };
240
- return () => h$1(clonedComponent, { ...props, ...setProps, ...attrs }, slots);
197
+ return () => h$1(clonedComponent, { ...props, ...setProps, ...attrs }, setupContext.slots);
241
198
  }
242
199
  })
243
200
  }
@@ -246,11 +203,18 @@ async function mountSuspended(component, options) {
246
203
  defu(
247
204
  _options,
248
205
  {
206
+ props,
249
207
  slots,
250
208
  attrs,
251
209
  global: {
252
210
  config: {
253
- globalProperties: vueApp.config.globalProperties
211
+ globalProperties: {
212
+ ...vueApp.config.globalProperties,
213
+ // make all properties/keys enumerable.
214
+ ...Object.fromEntries(
215
+ Object.getOwnPropertyNames(vueApp.config.globalProperties).map((key) => [key, vueApp.config.globalProperties[key]])
216
+ )
217
+ }
254
218
  },
255
219
  directives: vueApp._context.directives,
256
220
  provide: vueApp._context.provides,
@@ -267,58 +231,46 @@ async function mountSuspended(component, options) {
267
231
  }
268
232
  );
269
233
  }
270
- function cloneProps$1(props) {
271
- const newProps = reactive({});
272
- for (const key in props) {
273
- newProps[key] = props[key];
274
- }
275
- return newProps;
276
- }
277
234
  function wrappedMountedWrapper(wrapper) {
278
- const proxy = new Proxy(wrapper, {
279
- get: (target, prop, receiver) => {
280
- if (prop === "element") {
281
- const component = target.findComponent({ name: "MountSuspendedComponent" });
282
- return component[prop];
283
- } else if (prop === "vm") {
284
- const vm = Reflect.get(target, prop, receiver);
285
- return createVMProxy(vm, wrapper.setupState);
286
- } else {
287
- return Reflect.get(target, prop, receiver);
288
- }
235
+ const component = wrapper.findComponent({ name: "MountSuspendedComponent" });
236
+ const wrapperProps = [
237
+ "setProps",
238
+ "emitted",
239
+ "setupState",
240
+ "unmount"
241
+ ];
242
+ return new Proxy(wrapper, {
243
+ get: (_, prop, receiver) => {
244
+ if (prop === "getCurrentComponent") return getCurrentComponentPatchedProxy;
245
+ const target = wrapperProps.includes(prop) ? wrapper : Reflect.has(component, prop) ? component : wrapper;
246
+ const value = Reflect.get(target, prop, receiver);
247
+ return typeof value === "function" ? value.bind(target) : value;
289
248
  }
290
249
  });
291
- for (const key of ["props"]) {
292
- proxy[key] = new Proxy(wrapper[key], {
293
- apply: (target, thisArg, args) => {
294
- const component = thisArg.findComponent({ name: "MountSuspendedComponent" });
295
- return component[key](...args);
250
+ function getCurrentComponentPatchedProxy() {
251
+ const currentComponent = component.getCurrentComponent();
252
+ return new Proxy(currentComponent, {
253
+ get: (target, prop, receiver) => {
254
+ const value = Reflect.get(target, prop, receiver);
255
+ if (prop === "proxy" && value) {
256
+ return new Proxy(value, {
257
+ get(o, p, r) {
258
+ if (!Reflect.has(currentComponent.props, p)) {
259
+ const setupState = wrapper.setupState;
260
+ if (setupState && typeof setupState === "object") {
261
+ if (Reflect.has(setupState, p)) {
262
+ return Reflect.get(setupState, p, r);
263
+ }
264
+ }
265
+ }
266
+ return Reflect.get(o, p, r);
267
+ }
268
+ });
269
+ }
270
+ return value;
296
271
  }
297
272
  });
298
273
  }
299
- return proxy;
300
- }
301
- function createVMProxy(vm, setupState) {
302
- return new Proxy(vm, {
303
- get(target, key, receiver) {
304
- const value = Reflect.get(target, key, receiver);
305
- if (setupState && typeof setupState === "object" && key in setupState) {
306
- return unref(setupState[key]);
307
- }
308
- return value;
309
- },
310
- set(target, key, value, receiver) {
311
- if (setupState && typeof setupState === "object" && key in setupState) {
312
- const setupValue = setupState[key];
313
- if (setupValue && isRef(setupValue)) {
314
- setupValue.value = value;
315
- return true;
316
- }
317
- return Reflect.set(setupState, key, value, receiver);
318
- }
319
- return Reflect.set(target, key, value, receiver);
320
- }
321
- });
322
274
  }
323
275
 
324
276
  const WRAPPER_EL_ID = "test-wrapper";
@@ -332,38 +284,36 @@ async function renderSuspended(component, options) {
332
284
  } = options || {};
333
285
  const { render: renderFromTestingLibrary } = await import('@testing-library/vue');
334
286
  const vueApp = tryUseNuxtApp()?.vueApp || globalThis.__unctx__.get("nuxt-app").tryUse().vueApp;
335
- const { render, setup, data, computed, methods, ...componentRest } = component;
287
+ const { render, setup, ...componentRest } = component;
288
+ let wrappedInstance = null;
336
289
  let setupContext;
337
290
  let setupState;
338
291
  const setProps = reactive({});
339
- let interceptedEmit = null;
340
- function getInterceptedEmitFunction(emit) {
341
- if (emit !== interceptedEmit) {
342
- interceptedEmit = interceptedEmit ?? ((event, ...args) => {
343
- emit(event, ...args);
344
- setupContext.emit(event, ...args);
345
- });
292
+ function patchInstanceAppContext() {
293
+ const app = getCurrentInstance()?.appContext.app;
294
+ if (!app) return;
295
+ for (const [key, value] of Object.entries(vueApp)) {
296
+ if (key in app) continue;
297
+ app[key] = value;
346
298
  }
347
- return interceptedEmit;
348
- }
349
- function interceptEmitOnCurrentInstance() {
350
- const currentInstance = getCurrentInstance();
351
- if (!currentInstance) {
352
- return;
353
- }
354
- currentInstance.emit = getInterceptedEmitFunction(currentInstance.emit);
355
299
  }
356
300
  for (const fn of window.__cleanup || []) {
357
301
  fn();
358
302
  }
359
303
  document.querySelector(`#${WRAPPER_EL_ID}`)?.remove();
360
- let passedProps;
361
- const wrappedSetup = async (props2, setupContext2) => {
362
- interceptEmitOnCurrentInstance();
363
- passedProps = props2;
304
+ const wrappedSetup = async (props2, setupContext2, instanceContext) => {
305
+ const currentInstance = getCurrentInstance();
306
+ if (currentInstance) {
307
+ currentInstance.emit = (event, ...args) => {
308
+ setupContext2.emit(event, ...args);
309
+ };
310
+ }
364
311
  if (setup) {
365
312
  const result = await setup(props2, setupContext2);
366
313
  setupState = result && typeof result === "object" ? result : {};
314
+ if (wrappedInstance?.exposed) {
315
+ instanceContext.expose(wrappedInstance.exposed);
316
+ }
367
317
  return result;
368
318
  }
369
319
  };
@@ -377,7 +327,10 @@ async function renderSuspended(component, options) {
377
327
  const utils = renderFromTestingLibrary(
378
328
  {
379
329
  __cssModules: componentRest.__cssModules,
330
+ inheritAttrs: false,
380
331
  setup: (props2, ctx) => {
332
+ patchInstanceAppContext();
333
+ wrappedInstance = getCurrentInstance();
381
334
  setupContext = ctx;
382
335
  const scope = effectScope();
383
336
  window.__cleanup ||= [];
@@ -389,7 +342,7 @@ async function renderSuspended(component, options) {
389
342
  expose: () => ({})
390
343
  }));
391
344
  },
392
- render: (renderContext) => (
345
+ render: () => (
393
346
  // See discussions in https://github.com/testing-library/vue-testing-library/issues/230
394
347
  // we add this additional root element because otherwise testing-library breaks
395
348
  // because there's no root element while Suspense is resolving
@@ -416,56 +369,13 @@ async function renderSuspended(component, options) {
416
369
  const router = useRouter();
417
370
  await router.replace(route);
418
371
  const clonedComponent = {
419
- name: "RenderSuspendedComponent",
372
+ components: {},
420
373
  ...component,
421
- render: render ? function(_ctx, ...args) {
422
- interceptEmitOnCurrentInstance();
423
- if (data && typeof data === "function") {
424
- const dataObject = data();
425
- for (const key in dataObject) {
426
- renderContext[key] = dataObject[key];
427
- }
428
- }
429
- for (const key in setupState || {}) {
430
- const warn = console.warn;
431
- console.warn = () => {
432
- };
433
- try {
434
- renderContext[key] = isReadonly(setupState[key]) ? unref(setupState[key]) : setupState[key];
435
- } catch {
436
- } finally {
437
- console.warn = warn;
438
- }
439
- if (key === "props") {
440
- renderContext[key] = cloneProps(renderContext[key]);
441
- }
442
- }
443
- const propsContext = "props" in renderContext ? renderContext.props : renderContext;
444
- for (const key in props || {}) {
445
- propsContext[key] = _ctx[key];
446
- }
447
- for (const key in passedProps || {}) {
448
- propsContext[key] = passedProps[key];
449
- }
450
- if (methods && typeof methods === "object") {
451
- for (const [key, value] of Object.entries(methods)) {
452
- renderContext[key] = value.bind(renderContext);
453
- }
454
- }
455
- if (computed && typeof computed === "object") {
456
- for (const [key, value] of Object.entries(computed)) {
457
- if ("get" in value) {
458
- renderContext[key] = value.get.call(renderContext);
459
- } else {
460
- renderContext[key] = value.call(renderContext);
461
- }
462
- }
463
- }
464
- return render.call(this, renderContext, ...args);
465
- } : void 0,
466
- setup: (props2) => wrappedSetup(props2, setupContext)
374
+ name: "RenderSuspendedComponent",
375
+ render,
376
+ setup: (props2, ctx) => wrappedSetup(props2, setupContext, ctx)
467
377
  };
468
- return () => h$1(clonedComponent, { ...props && typeof props === "object" ? props : {}, ...setProps, ...attrs }, slots);
378
+ return () => h$1(clonedComponent, { ...props && typeof props === "object" ? props : {}, ...setProps, ...attrs }, setupContext.slots);
469
379
  }
470
380
  })
471
381
  }
@@ -475,11 +385,18 @@ async function renderSuspended(component, options) {
475
385
  )
476
386
  },
477
387
  defu(_options, {
388
+ props,
478
389
  slots,
479
390
  attrs,
480
391
  global: {
481
392
  config: {
482
- globalProperties: vueApp.config.globalProperties
393
+ globalProperties: {
394
+ ...vueApp.config.globalProperties,
395
+ // make all properties/keys enumerable.
396
+ ...Object.fromEntries(
397
+ Object.getOwnPropertyNames(vueApp.config.globalProperties).map((key) => [key, vueApp.config.globalProperties[key]])
398
+ )
399
+ }
483
400
  },
484
401
  directives: vueApp._context.directives,
485
402
  provide: vueApp._context.provides,
@@ -489,12 +406,5 @@ async function renderSuspended(component, options) {
489
406
  );
490
407
  });
491
408
  }
492
- function cloneProps(props) {
493
- const newProps = reactive({});
494
- for (const key in props) {
495
- newProps[key] = props[key];
496
- }
497
- return newProps;
498
- }
499
409
 
500
410
  export { mockComponent, mockNuxtImport, mountSuspended, registerEndpoint, renderSuspended };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuxt/test-utils-nightly",
3
- "version": "3.21.0-20251031-123045-c452751",
3
+ "version": "3.21.0-20251204-130449-b6179fd",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/nuxt/test-utils.git"
@@ -73,34 +73,34 @@
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
+ "fake-indexeddb": "^6.2.5",
77
77
  "get-port-please": "^3.2.0",
78
78
  "h3": "^1.15.4",
79
79
  "local-pkg": "^1.1.2",
80
80
  "magic-string": "^0.30.21",
81
81
  "node-fetch-native": "^1.6.7",
82
82
  "node-mock-http": "^1.0.3",
83
- "ofetch": "^1.4.1",
83
+ "ofetch": "^1.5.1",
84
84
  "pathe": "^2.0.3",
85
85
  "perfect-debounce": "^2.0.0",
86
86
  "radix3": "^1.1.2",
87
87
  "scule": "^1.3.0",
88
88
  "std-env": "^3.10.0",
89
- "tinyexec": "^1.0.1",
89
+ "tinyexec": "^1.0.2",
90
90
  "ufo": "^1.6.1",
91
91
  "unplugin": "^2.3.10",
92
92
  "vitest-environment-nuxt": "^1.0.1",
93
- "vue": "^3.5.22"
93
+ "vue": "^3.5.24"
94
94
  },
95
95
  "devDependencies": {
96
96
  "@cucumber/cucumber": "12.2.0",
97
97
  "@jest/globals": "30.2.0",
98
98
  "@nuxt/devtools-kit": "2.7.0",
99
- "@nuxt/eslint-config": "1.9.0",
99
+ "@nuxt/eslint-config": "1.10.0",
100
100
  "@nuxt/schema": "4.1.3",
101
101
  "@playwright/test": "1.56.1",
102
102
  "@testing-library/vue": "8.1.0",
103
- "@types/bun": "1.3.1",
103
+ "@types/bun": "1.3.2",
104
104
  "@types/estree": "1.0.8",
105
105
  "@types/jsdom": "27.0.0",
106
106
  "@types/node": "latest",
@@ -108,22 +108,22 @@
108
108
  "@vue/test-utils": "2.4.6",
109
109
  "changelogen": "0.6.2",
110
110
  "compatx": "0.2.0",
111
- "eslint": "9.38.0",
111
+ "eslint": "9.39.1",
112
112
  "installed-check": "9.3.0",
113
- "knip": "5.66.3",
114
- "nitropack": "2.12.8",
113
+ "knip": "5.68.0",
114
+ "nitropack": "2.12.9",
115
115
  "nuxt": "4.1.3",
116
116
  "pkg-pr-new": "0.0.60",
117
117
  "playwright-core": "1.56.1",
118
- "rollup": "4.52.5",
118
+ "rollup": "4.53.2",
119
119
  "semver": "7.7.3",
120
120
  "typescript": "5.9.3",
121
121
  "unbuild": "latest",
122
122
  "unimport": "5.5.0",
123
- "vite": "7.1.12",
123
+ "vite": "7.2.2",
124
124
  "vitest": "3.2.4",
125
125
  "vue-router": "4.6.3",
126
- "vue-tsc": "3.1.2"
126
+ "vue-tsc": "3.1.3"
127
127
  },
128
128
  "peerDependencies": {
129
129
  "@cucumber/cucumber": "^10.3.1 || >=11.0.0",
@@ -174,14 +174,14 @@
174
174
  "@nuxt/schema": "4.1.3",
175
175
  "@nuxt/test-utils": "workspace:*",
176
176
  "@types/node": "22.18.8",
177
- "rollup": "4.52.5",
178
- "vite": "7.1.12",
177
+ "rollup": "4.53.2",
178
+ "vite": "7.2.2",
179
179
  "vite-node": "3.2.4",
180
180
  "vitest": "3.2.4",
181
- "vue": "^3.5.22"
181
+ "vue": "^3.5.24"
182
182
  },
183
183
  "engines": {
184
184
  "node": "^20.0.0 || ^22.0.0 || >=24.0.0"
185
185
  },
186
- "packageManager": "pnpm@10.19.0"
186
+ "packageManager": "pnpm@10.21.0"
187
187
  }