@nuxt/test-utils 3.21.0 → 3.23.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.
Files changed (32) hide show
  1. package/README.md +1 -1
  2. package/dist/config.d.mts +3 -3
  3. package/dist/config.mjs +40 -21
  4. package/dist/e2e.d.mts +3 -2
  5. package/dist/e2e.mjs +17 -13
  6. package/dist/experimental.mjs +1 -1
  7. package/dist/module.mjs +721 -148
  8. package/dist/playwright.d.mts +2 -1
  9. package/dist/playwright.mjs +3 -3
  10. package/dist/runtime/shared/environment.mjs +11 -66
  11. package/dist/runtime/shared/h3-v1.d.ts +6 -0
  12. package/dist/runtime/shared/h3-v1.mjs +69 -0
  13. package/dist/runtime/shared/h3-v2.d.ts +6 -0
  14. package/dist/runtime/shared/h3-v2.mjs +35 -0
  15. package/dist/runtime/shared/h3.d.ts +3 -0
  16. package/dist/runtime/shared/h3.mjs +3 -0
  17. package/dist/runtime/shared/nuxt.d.ts +1 -1
  18. package/dist/runtime/shared/nuxt.mjs +10 -2
  19. package/dist/runtime/shared/vue-wrapper-plugin.d.ts +50 -0
  20. package/dist/runtime/shared/vue-wrapper-plugin.mjs +41 -0
  21. package/dist/runtime-utils/index.d.mts +26 -25
  22. package/dist/runtime-utils/index.mjs +185 -272
  23. package/dist/shared/{test-utils.3NR-so9-.mjs → test-utils.5cnw0YZR.mjs} +2 -2
  24. package/dist/shared/{test-utils.G1ew4kEe.mjs → test-utils.BIY9XRkB.mjs} +1 -1
  25. package/dist/shared/{test-utils.CtwoJP76.mjs → test-utils.BsmyE2FA.mjs} +10 -8
  26. package/dist/shared/{test-utils.20kU0tZa.d.mts → test-utils.C9GKP_T5.d.mts} +3 -2
  27. package/dist/shared/test-utils.DDUpsMYL.mjs +32 -0
  28. package/dist/vitest-environment.d.mts +15 -3
  29. package/dist/vitest-environment.mjs +118 -66
  30. package/dist/vitest-wrapper/cli.d.mts +2 -0
  31. package/dist/vitest-wrapper/cli.mjs +78 -0
  32. package/package.json +32 -26
@@ -1,6 +1,5 @@
1
- import { defineEventHandler } from 'h3';
2
1
  import { mount } from '@vue/test-utils';
3
- import { reactive, h as h$1, Suspense, nextTick, getCurrentInstance, effectScope, defineComponent as defineComponent$1 } from 'vue';
2
+ import { reactive, h as h$1, Suspense, nextTick as nextTick$1, getCurrentInstance, onErrorCaptured, effectScope } from 'vue';
4
3
  import { defu } from 'defu';
5
4
  import { defineComponent, useRouter, h, tryUseNuxtApp } from '#imports';
6
5
  import NuxtRoot from '#build/root-component.mjs';
@@ -12,30 +11,11 @@ function registerEndpoint(url, options) {
12
11
  throw new Error("registerEndpoint() can only be used in a `@nuxt/test-utils` runtime environment");
13
12
  }
14
13
  const config = typeof options === "function" ? { handler: options, method: void 0, once: false } : options;
15
- config.handler = defineEventHandler(config.handler);
16
- const hasBeenRegistered = window.__registry.has(url);
14
+ config.handler = Object.assign(config.handler, { __is_handler__: true });
17
15
  endpointRegistry[url] ||= [];
18
16
  endpointRegistry[url].push(config);
19
- if (!hasBeenRegistered) {
20
- window.__registry.add(url);
21
- app.use("/_" + url, defineEventHandler(async (event) => {
22
- const latestHandler = [...endpointRegistry[url] || []].reverse().find((config2) => config2.method ? event.method === config2.method : true);
23
- if (!latestHandler) return;
24
- const result = await latestHandler.handler(event);
25
- if (!latestHandler.once) return result;
26
- const index = endpointRegistry[url]?.indexOf(latestHandler);
27
- if (index === void 0 || index === -1) return result;
28
- endpointRegistry[url]?.splice(index, 1);
29
- if (endpointRegistry[url]?.length === 0) {
30
- window.__registry.delete(url);
31
- }
32
- return result;
33
- }), {
34
- match(_, event) {
35
- return endpointRegistry[url]?.some((config2) => config2.method ? event?.method === config2.method : true) ?? false;
36
- }
37
- });
38
- }
17
+ window.__registry.add(url);
18
+ app._registered ||= registerGlobalHandler(app);
39
19
  return () => {
40
20
  endpointRegistry[url]?.splice(endpointRegistry[url].indexOf(config), 1);
41
21
  if (endpointRegistry[url]?.length === 0) {
@@ -53,6 +33,31 @@ function mockComponent(_path, _component) {
53
33
  "mockComponent() is a macro and it did not get transpiled. This may be an internal bug of @nuxt/test-utils."
54
34
  );
55
35
  }
36
+ const handler = Object.assign(async (event) => {
37
+ const url = "url" in event && event.url ? event.url.pathname.replace(/^\/_/, "") : event.path.replace(/[?#].*$/, "").replace(/^\/_/, "");
38
+ const latestHandler = [...endpointRegistry[url] || []].reverse().find((config) => config.method ? event.method === config.method : true);
39
+ if (!latestHandler) return;
40
+ const result = await latestHandler.handler(event);
41
+ if (!latestHandler.once) return result;
42
+ const index = endpointRegistry[url]?.indexOf(latestHandler);
43
+ if (index === void 0 || index === -1) return result;
44
+ endpointRegistry[url]?.splice(index, 1);
45
+ if (endpointRegistry[url]?.length === 0) {
46
+ window.__registry.delete(url);
47
+ }
48
+ return result;
49
+ }, { __is_handler__: true });
50
+ function registerGlobalHandler(app) {
51
+ app.use(handler, {
52
+ match: (...args) => {
53
+ const [eventOrPath, _event = eventOrPath] = args;
54
+ const url = typeof eventOrPath === "string" ? eventOrPath.replace(/^\/_/, "").replace(/[?#].*$/, "") : eventOrPath.url.pathname.replace(/^\/_/, "");
55
+ const event = _event;
56
+ return endpointRegistry[url]?.some((config) => config.method ? event?.method === config.method : true) ?? false;
57
+ }
58
+ });
59
+ return true;
60
+ }
56
61
 
57
62
  const RouterLink = defineComponent({
58
63
  functional: true,
@@ -88,19 +93,34 @@ const RouterLink = defineComponent({
88
93
  }
89
94
  });
90
95
 
91
- async function mountSuspended(component, options) {
92
- const {
93
- props = {},
94
- attrs = {},
95
- slots = {},
96
- route = "/",
97
- ..._options
98
- } = options || {};
99
- for (const cleanupFunction of globalThis.__cleanup || []) {
100
- cleanupFunction();
96
+ function cleanupAll() {
97
+ for (const fn of (window.__cleanup || []).splice(0)) {
98
+ fn();
101
99
  }
100
+ }
101
+ function addCleanup(fn) {
102
+ window.__cleanup ||= [];
103
+ window.__cleanup.push(fn);
104
+ }
105
+ function runEffectScope(fn) {
106
+ const scope = effectScope();
107
+ addCleanup(() => scope.stop());
108
+ return scope.run(fn);
109
+ }
110
+ function wrapperSuspended(component, options, {
111
+ wrapperFn,
112
+ wrappedRender = (fn) => fn,
113
+ suspendedHelperName,
114
+ clonedComponentName
115
+ }) {
116
+ const { props = {}, attrs = {} } = options;
117
+ const { route = "/", scoped = false, ...wrapperFnOptions } = options;
102
118
  const vueApp = tryUseNuxtApp()?.vueApp || globalThis.__unctx__.get("nuxt-app").tryUse().vueApp;
103
- const { render, setup, ...componentRest } = component;
119
+ const {
120
+ render: componentRender,
121
+ setup: componentSetup,
122
+ ...componentRest
123
+ } = component;
104
124
  let wrappedInstance = null;
105
125
  let setupContext;
106
126
  let setupState;
@@ -113,28 +133,19 @@ async function mountSuspended(component, options) {
113
133
  app[key] = value;
114
134
  }
115
135
  }
116
- let componentScope = null;
117
- const wrappedSetup = async (props2, setupContext2, instanceContext) => {
118
- const currentInstance = getCurrentInstance();
119
- if (currentInstance) {
120
- currentInstance.emit = (event, ...args) => {
121
- setupContext2.emit(event, ...args);
122
- };
123
- }
124
- if (setup) {
125
- let result;
126
- if (options?.scoped) {
127
- componentScope = effectScope();
128
- globalThis.__cleanup ||= [];
129
- globalThis.__cleanup.push(() => {
130
- componentScope?.stop();
131
- });
132
- result = await componentScope?.run(async () => {
133
- return await setup(props2, setupContext2);
134
- });
135
- } else {
136
- result = await setup(props2, setupContext2);
136
+ const ClonedComponent = {
137
+ components: {},
138
+ ...component,
139
+ name: clonedComponentName,
140
+ async setup(props2, instanceContext) {
141
+ const currentInstance = getCurrentInstance();
142
+ if (currentInstance) {
143
+ currentInstance.emit = (event, ...args) => {
144
+ setupContext.emit(event, ...args);
145
+ };
137
146
  }
147
+ if (!componentSetup) return;
148
+ const result = scoped ? await runEffectScope(() => componentSetup(props2, setupContext)) : await componentSetup(props2, setupContext);
138
149
  if (wrappedInstance?.exposed) {
139
150
  instanceContext.expose(wrappedInstance.exposed);
140
151
  }
@@ -142,97 +153,110 @@ async function mountSuspended(component, options) {
142
153
  return result;
143
154
  }
144
155
  };
145
- return new Promise(
146
- (resolve) => {
147
- const vm = mount(
148
- {
149
- __cssModules: componentRest.__cssModules,
150
- inheritAttrs: false,
151
- setup: (props2, ctx) => {
152
- patchInstanceAppContext();
153
- wrappedInstance = getCurrentInstance();
154
- setupContext = ctx;
155
- if (options?.scoped) {
156
- const scope = effectScope();
157
- globalThis.__cleanup ||= [];
158
- globalThis.__cleanup.push(() => {
159
- scope.stop();
160
- });
161
- return scope.run(() => NuxtRoot.setup(props2, {
162
- ...ctx,
163
- expose: () => {
164
- }
165
- }));
166
- } else {
167
- return NuxtRoot.setup(props2, {
168
- ...ctx,
169
- expose: () => {
170
- }
171
- });
172
- }
173
- },
174
- render: () => h$1(
175
- Suspense,
176
- {
177
- onResolve: () => nextTick().then(() => {
178
- vm.setupState = setupState;
179
- vm.__setProps = (props2) => {
180
- Object.assign(setProps, props2);
181
- };
182
- resolve(wrappedMountedWrapper(vm));
183
- })
184
- },
185
- {
186
- default: () => h$1({
187
- name: "MountSuspendedHelper",
188
- async setup() {
189
- const router = useRouter();
190
- await router.replace(route);
191
- const clonedComponent = {
192
- components: {},
193
- ...component,
194
- name: "MountSuspendedComponent",
195
- setup: (props2, ctx) => wrappedSetup(props2, setupContext, ctx)
196
- };
197
- return () => h$1(clonedComponent, { ...props, ...setProps, ...attrs }, setupContext.slots);
198
- }
199
- })
156
+ const SuspendedHelper = {
157
+ name: suspendedHelperName,
158
+ render: () => "",
159
+ async setup() {
160
+ if (route) {
161
+ const router = useRouter();
162
+ await router.replace(route);
163
+ }
164
+ return () => h$1(ClonedComponent, { ...props, ...setProps, ...attrs }, setupContext.slots);
165
+ }
166
+ };
167
+ return new Promise((resolve, reject) => {
168
+ let isMountSettled = false;
169
+ const wrapper = wrapperFn(
170
+ {
171
+ inheritAttrs: false,
172
+ __cssModules: componentRest.__cssModules,
173
+ setup: (props2, ctx) => {
174
+ patchInstanceAppContext();
175
+ wrappedInstance = getCurrentInstance();
176
+ setupContext = ctx;
177
+ const nuxtRootSetupResult = runEffectScope(
178
+ () => NuxtRoot.setup(props2, {
179
+ ...ctx,
180
+ expose: () => {
181
+ }
182
+ })
183
+ );
184
+ onErrorCaptured((error, ...args) => {
185
+ if (isMountSettled) return;
186
+ isMountSettled = true;
187
+ try {
188
+ wrappedInstance?.appContext.config.errorHandler?.(error, ...args);
189
+ reject(error);
190
+ } catch (error2) {
191
+ reject(error2);
200
192
  }
201
- )
193
+ return false;
194
+ });
195
+ return nuxtRootSetupResult;
202
196
  },
203
- defu(
204
- _options,
197
+ render: wrappedRender(() => h$1(
198
+ Suspense,
205
199
  {
206
- props,
207
- slots,
208
- attrs,
209
- global: {
210
- config: {
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
- )
200
+ onResolve: () => nextTick$1().then(() => {
201
+ if (isMountSettled) return;
202
+ isMountSettled = true;
203
+ wrapper.setupState = setupState;
204
+ resolve({
205
+ wrapper,
206
+ setProps: (props2) => {
207
+ Object.assign(setProps, props2);
217
208
  }
218
- },
219
- directives: vueApp._context.directives,
220
- provide: vueApp._context.provides,
221
- stubs: {
222
- Suspense: false,
223
- MountSuspendedHelper: false,
224
- [component && typeof component === "object" && "name" in component && typeof component.name === "string" ? component.name : "MountSuspendedComponent"]: false
225
- },
226
- components: { ...vueApp._context.components, RouterLink }
227
- }
209
+ });
210
+ })
211
+ },
212
+ {
213
+ default: () => h$1(SuspendedHelper)
228
214
  }
229
- )
230
- );
231
- }
232
- );
215
+ ))
216
+ },
217
+ defu(wrapperFnOptions, {
218
+ global: {
219
+ config: {
220
+ globalProperties: makeAllPropertiesEnumerable(
221
+ vueApp.config.globalProperties
222
+ )
223
+ },
224
+ directives: vueApp._context.directives,
225
+ provide: vueApp._context.provides,
226
+ stubs: {
227
+ Suspense: false,
228
+ [SuspendedHelper.name]: false,
229
+ [ClonedComponent.name]: false
230
+ },
231
+ components: { ...vueApp._context.components, RouterLink }
232
+ }
233
+ })
234
+ );
235
+ });
236
+ }
237
+ function makeAllPropertiesEnumerable(target) {
238
+ return {
239
+ ...target,
240
+ ...Object.fromEntries(
241
+ Object.getOwnPropertyNames(target).map((key) => [key, target[key]])
242
+ )
243
+ };
233
244
  }
234
- function wrappedMountedWrapper(wrapper) {
235
- const component = wrapper.findComponent({ name: "MountSuspendedComponent" });
245
+
246
+ async function mountSuspended(component, options = {}) {
247
+ const suspendedHelperName = "MountSuspendedHelper";
248
+ const clonedComponentName = "MountSuspendedComponent";
249
+ cleanupAll();
250
+ const { wrapper, setProps } = await wrapperSuspended(component, options, {
251
+ wrapperFn: mount,
252
+ suspendedHelperName,
253
+ clonedComponentName
254
+ });
255
+ Object.assign(wrapper, { __setProps: setProps });
256
+ const clonedComponent = wrapper.findComponent({ name: clonedComponentName });
257
+ return wrappedMountedWrapper(wrapper, clonedComponent);
258
+ }
259
+ function wrappedMountedWrapper(wrapper, component) {
236
260
  const wrapperProps = [
237
261
  "setProps",
238
262
  "emitted",
@@ -273,138 +297,27 @@ function wrappedMountedWrapper(wrapper) {
273
297
  }
274
298
  }
275
299
 
276
- const WRAPPER_EL_ID = "test-wrapper";
277
- async function renderSuspended(component, options) {
278
- const {
279
- props = {},
280
- attrs = {},
281
- slots = {},
282
- route = "/",
283
- ..._options
284
- } = options || {};
285
- const { render: renderFromTestingLibrary } = await import('@testing-library/vue');
286
- const vueApp = tryUseNuxtApp()?.vueApp || globalThis.__unctx__.get("nuxt-app").tryUse().vueApp;
287
- const { render, setup, ...componentRest } = component;
288
- let wrappedInstance = null;
289
- let setupContext;
290
- let setupState;
291
- const setProps = reactive({});
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;
298
- }
299
- }
300
- for (const fn of window.__cleanup || []) {
301
- fn();
302
- }
303
- document.querySelector(`#${WRAPPER_EL_ID}`)?.remove();
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
- }
311
- if (setup) {
312
- const result = await setup(props2, setupContext2);
313
- setupState = result && typeof result === "object" ? result : {};
314
- if (wrappedInstance?.exposed) {
315
- instanceContext.expose(wrappedInstance.exposed);
316
- }
317
- return result;
318
- }
319
- };
320
- const WrapperComponent = defineComponent$1({
321
- inheritAttrs: false,
322
- render() {
323
- return h$1("div", { id: WRAPPER_EL_ID }, this.$slots.default?.());
324
- }
325
- });
326
- return new Promise((resolve) => {
327
- const utils = renderFromTestingLibrary(
328
- {
329
- __cssModules: componentRest.__cssModules,
330
- inheritAttrs: false,
331
- setup: (props2, ctx) => {
332
- patchInstanceAppContext();
333
- wrappedInstance = getCurrentInstance();
334
- setupContext = ctx;
335
- const scope = effectScope();
336
- window.__cleanup ||= [];
337
- window.__cleanup.push(() => {
338
- scope.stop();
339
- });
340
- return scope.run(() => NuxtRoot.setup(props2, {
341
- ...ctx,
342
- expose: () => ({})
343
- }));
344
- },
345
- render: () => (
346
- // See discussions in https://github.com/testing-library/vue-testing-library/issues/230
347
- // we add this additional root element because otherwise testing-library breaks
348
- // because there's no root element while Suspense is resolving
349
- h$1(
350
- WrapperComponent,
351
- {},
352
- {
353
- default: () => h$1(
354
- Suspense,
355
- {
356
- onResolve: () => nextTick().then(() => {
357
- utils.setupState = setupState;
358
- utils.rerender = async (props2) => {
359
- Object.assign(setProps, props2);
360
- await nextTick();
361
- };
362
- resolve(utils);
363
- })
364
- },
365
- {
366
- default: () => h$1({
367
- name: "RenderHelper",
368
- async setup() {
369
- const router = useRouter();
370
- await router.replace(route);
371
- const clonedComponent = {
372
- components: {},
373
- ...component,
374
- name: "RenderSuspendedComponent",
375
- render,
376
- setup: (props2, ctx) => wrappedSetup(props2, setupContext, ctx)
377
- };
378
- return () => h$1(clonedComponent, { ...props && typeof props === "object" ? props : {}, ...setProps, ...attrs }, setupContext.slots);
379
- }
380
- })
381
- }
382
- )
383
- }
384
- )
385
- )
386
- },
387
- defu(_options, {
388
- props,
389
- slots,
390
- attrs,
391
- global: {
392
- config: {
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
- }
400
- },
401
- directives: vueApp._context.directives,
402
- provide: vueApp._context.provides,
403
- components: { RouterLink }
404
- }
405
- })
406
- );
300
+ async function renderSuspended(component, options = {}) {
301
+ const wrapperId = "test-wrapper";
302
+ const suspendedHelperName = "RenderHelper";
303
+ const clonedComponentName = "RenderSuspendedComponent";
304
+ const { render: wrapperFn } = await import('@testing-library/vue');
305
+ cleanupAll();
306
+ document.getElementById(wrapperId)?.remove();
307
+ const { wrapper, setProps } = await wrapperSuspended(component, options, {
308
+ wrapperFn,
309
+ wrappedRender: (render) => () => h$1({
310
+ inheritAttrs: false,
311
+ render: () => h$1("div", { id: wrapperId }, render())
312
+ }),
313
+ suspendedHelperName,
314
+ clonedComponentName
407
315
  });
316
+ wrapper.rerender = async (props) => {
317
+ setProps(props);
318
+ await nextTick();
319
+ };
320
+ return wrapper;
408
321
  }
409
322
 
410
323
  export { mockComponent, mockNuxtImport, mountSuspended, registerEndpoint, renderSuspended };
@@ -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.BsmyE2FA.mjs';
2
2
  import { existsSync, promises } from 'node:fs';
3
3
  import { resolve } from 'node:path';
4
4
  import { defu } from 'defu';
5
- import { l as loadKit } from './test-utils.G1ew4kEe.mjs';
5
+ import { l as loadKit } from './test-utils.BIY9XRkB.mjs';
6
6
 
7
7
  async function createBrowser() {
8
8
  const ctx = useTestContext();
@@ -48,7 +48,7 @@ async function loadKit(rootDir) {
48
48
  } catch (e) {
49
49
  if (e.toString().includes("Cannot find module '@nuxt/kit'")) {
50
50
  throw new Error(
51
- "nuxi requires `@nuxt/kit` to be installed in your project. Try installing `nuxt` v3+ or `@nuxt/bridge` first."
51
+ "`@nuxt/test-utils` requires `@nuxt/kit` to be installed in your project. Try installing `nuxt` v3+ or `@nuxt/bridge` first."
52
52
  );
53
53
  }
54
54
  throw e;
@@ -1,6 +1,6 @@
1
1
  import { x } from 'tinyexec';
2
2
  import { getRandomPort, waitForPort } from 'get-port-please';
3
- import { $fetch as $fetch$1, fetch as fetch$1 } from 'ofetch';
3
+ import { createFetch, fetch as fetch$1 } from 'ofetch';
4
4
  import { resolve as resolve$1 } from 'pathe';
5
5
  import { withTrailingSlash, joinURL } from 'ufo';
6
6
  import { resolve } from 'node:path';
@@ -72,6 +72,7 @@ function exposeContextToEnv() {
72
72
  process.env.NUXT_TEST_CONTEXT = JSON.stringify({ options, browser, url });
73
73
  }
74
74
 
75
+ const globalFetch = globalThis.fetch || fetch$1;
75
76
  async function startServer(options = {}) {
76
77
  const ctx = useTestContext();
77
78
  await stopServer();
@@ -91,8 +92,8 @@ async function startServer(options = {}) {
91
92
  PORT: String(port),
92
93
  HOST: host,
93
94
  NODE_ENV: "development",
94
- ...options.env,
95
- ...ctx.options.env
95
+ ...ctx.options.env,
96
+ ...options.env
96
97
  }
97
98
  }
98
99
  });
@@ -128,8 +129,8 @@ async function startServer(options = {}) {
128
129
  PORT: String(port),
129
130
  HOST: host,
130
131
  NODE_ENV: "test",
131
- ...options.env,
132
- ...ctx.options.env
132
+ ...ctx.options.env,
133
+ ...options.env
133
134
  }
134
135
  }
135
136
  }
@@ -144,10 +145,11 @@ async function stopServer() {
144
145
  }
145
146
  }
146
147
  function fetch(path, options) {
147
- return fetch$1(url(path), options);
148
+ return globalFetch(url(path), options);
148
149
  }
149
- const $fetch = function(path, options) {
150
- return $fetch$1(url(path), options);
150
+ const _$fetch = createFetch({ fetch: globalFetch });
151
+ const $fetch = function $fetch2(path, options) {
152
+ return _$fetch(url(path), options);
151
153
  };
152
154
  function url(path) {
153
155
  const ctx = useTestContext();
@@ -1,6 +1,7 @@
1
1
  import { Browser, Page, Response as Response$1, BrowserContextOptions, LaunchOptions } from 'playwright-core';
2
2
  import { NuxtConfig, Nuxt } from '@nuxt/schema';
3
3
  import { exec } from 'tinyexec';
4
+ import { $Fetch } from 'ofetch';
4
5
 
5
6
  declare function createBrowser(): Promise<void>;
6
7
  declare function getBrowser(): Promise<Browser>;
@@ -20,7 +21,7 @@ interface StartServerOptions {
20
21
  declare function startServer(options?: StartServerOptions): Promise<void>;
21
22
  declare function stopServer(): Promise<void>;
22
23
  declare function fetch(path: string, options?: RequestInit): Promise<Response>;
23
- declare const $fetch: (typeof globalThis)["$fetch"];
24
+ declare const $fetch: "$fetch" extends keyof typeof globalThis ? typeof globalThis.$fetch : $Fetch;
24
25
  declare function url(path: string): string;
25
26
 
26
27
  type TestRunner = 'vitest' | 'jest' | 'cucumber' | 'bun';
@@ -116,4 +117,4 @@ interface TestHooks {
116
117
  }
117
118
 
118
119
  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 };
120
+ export type { GotoOptions as G, NuxtPage as N, StartServerOptions as S, TestOptions as T, TestHooks as a, TestContext as b, TestRunner as h };
@@ -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 };
@@ -1,13 +1,25 @@
1
1
  import { Environment } from 'vitest/environments';
2
- import { App } from 'h3';
2
+ import { H3Event as H3Event$1 } from 'h3';
3
+ import { H3Event } from 'h3-next';
3
4
  import { $Fetch } from 'nitropack';
4
5
  import { JSDOMOptions, HappyDOMOptions } from 'vitest/node';
5
6
 
6
7
  declare const _default: Environment;
7
8
 
8
9
  type NuxtBuiltinEnvironment = 'happy-dom' | 'jsdom';
10
+ interface GenericAppUse {
11
+ (route: string, handler: (event: H3Event | H3Event$1) => unknown, options?: {
12
+ match: (...args: [string, H3Event$1 | undefined] | [H3Event]) => boolean;
13
+ }): void;
14
+ (handler: (event: H3Event | H3Event$1) => unknown, options?: {
15
+ match: (...args: [string, H3Event$1 | undefined] | [H3Event]) => boolean;
16
+ }): void;
17
+ }
18
+ interface GenericApp {
19
+ use: GenericAppUse;
20
+ }
9
21
  interface NuxtWindow extends Window {
10
- __app: App;
22
+ __app?: GenericApp;
11
23
  __registry: Set<string>;
12
24
  __NUXT_VITEST_ENVIRONMENT__?: boolean;
13
25
  __NUXT__: Record<string, unknown>;
@@ -26,4 +38,4 @@ type EnvironmentNuxt = (global: typeof globalThis, options: EnvironmentNuxtOptio
26
38
  }>;
27
39
 
28
40
  export { _default as default };
29
- export type { EnvironmentNuxt, EnvironmentNuxtOptions, NuxtBuiltinEnvironment, NuxtWindow };
41
+ export type { EnvironmentNuxt, EnvironmentNuxtOptions, GenericApp, NuxtBuiltinEnvironment, NuxtWindow };