@nuxt/test-utils 3.19.2 → 3.20.1
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/config.d.mts +3 -3
- package/dist/e2e.d.mts +2 -2
- package/dist/e2e.mjs +3 -3
- package/dist/experimental.mjs +1 -1
- package/dist/module.mjs +1 -1
- package/dist/playwright.d.mts +1 -1
- package/dist/playwright.mjs +2 -2
- package/dist/runtime/shared/environment.mjs +37 -12
- package/dist/runtime-utils/index.d.mts +4 -0
- package/dist/runtime-utils/index.mjs +101 -19
- package/dist/shared/{test-utils.DtJCg4f3.d.mts → test-utils.20kU0tZa.d.mts} +11 -11
- package/dist/shared/{test-utils.CT3RJOY3.mjs → test-utils.CtoalVlS.mjs} +2 -2
- package/dist/shared/{test-utils.B8qEdk9k.mjs → test-utils.CtwoJP76.mjs} +1 -1
- package/dist/vitest-environment.mjs +57 -22
- package/package.json +56 -51
package/dist/config.d.mts
CHANGED
|
@@ -24,7 +24,7 @@ interface NuxtEnvironmentOptions {
|
|
|
24
24
|
rootDir?: string;
|
|
25
25
|
/**
|
|
26
26
|
* The starting URL for your Nuxt window environment
|
|
27
|
-
* @default
|
|
27
|
+
* @default 'http://localhost:3000'
|
|
28
28
|
*/
|
|
29
29
|
url?: string;
|
|
30
30
|
/**
|
|
@@ -37,14 +37,14 @@ interface NuxtEnvironmentOptions {
|
|
|
37
37
|
overrides?: NuxtConfig;
|
|
38
38
|
/**
|
|
39
39
|
* The id of the root div to which the app should be mounted. You should also set `app.rootId` to the same value.
|
|
40
|
-
* @default
|
|
40
|
+
* @default 'nuxt-test'
|
|
41
41
|
*/
|
|
42
42
|
rootId?: string;
|
|
43
43
|
/**
|
|
44
44
|
* The name of the DOM environment to use.
|
|
45
45
|
*
|
|
46
46
|
* It also needs to be installed as a dev dependency in your project.
|
|
47
|
-
* @default
|
|
47
|
+
* @default 'happy-dom'
|
|
48
48
|
*/
|
|
49
49
|
domEnvironment?: 'happy-dom' | 'jsdom';
|
|
50
50
|
mock?: {
|
package/dist/e2e.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { T as TestOptions, a as TestContext, b as TestHooks } from './shared/test-utils.
|
|
2
|
-
export { $ as $fetch, G as GotoOptions, N as NuxtPage, S as StartServerOptions, h as TestRunner, c as createBrowser, d as createPage, f as fetch, g as getBrowser, s as startServer, e as stopServer, u as url, w as waitForHydration } from './shared/test-utils.
|
|
1
|
+
import { T as TestOptions, a as TestContext, b as TestHooks } from './shared/test-utils.20kU0tZa.mjs';
|
|
2
|
+
export { $ as $fetch, G as GotoOptions, N as NuxtPage, S as StartServerOptions, h as TestRunner, c as createBrowser, d as createPage, f as fetch, g as getBrowser, s as startServer, e as stopServer, u as url, w as waitForHydration } from './shared/test-utils.20kU0tZa.mjs';
|
|
3
3
|
import { LogType } from 'consola';
|
|
4
4
|
import 'playwright-core';
|
|
5
5
|
import '@nuxt/schema';
|
package/dist/e2e.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { b as buildFixture, c as createBrowser, a as createPage, d as createTest, g as getBrowser, l as loadFixture, e as setup, s as setupMaps, w as waitForHydration } from './shared/test-utils.
|
|
2
|
-
import { u as useTestContext } from './shared/test-utils.
|
|
3
|
-
export { $ as $fetch, c as createTestContext, e as exposeContextToEnv, f as fetch, i as isDev, r as recoverContextFromEnv, s as setTestContext, a as startServer, b as stopServer, d as url } from './shared/test-utils.
|
|
1
|
+
export { b as buildFixture, c as createBrowser, a as createPage, d as createTest, g as getBrowser, l as loadFixture, e as setup, s as setupMaps, w as waitForHydration } from './shared/test-utils.CtoalVlS.mjs';
|
|
2
|
+
import { u as useTestContext } from './shared/test-utils.CtwoJP76.mjs';
|
|
3
|
+
export { $ as $fetch, c as createTestContext, e as exposeContextToEnv, f as fetch, i as isDev, r as recoverContextFromEnv, s as setTestContext, a as startServer, b as stopServer, d as url } from './shared/test-utils.CtwoJP76.mjs';
|
|
4
4
|
import { consola } from 'consola';
|
|
5
5
|
import { resolve } from 'pathe';
|
|
6
6
|
import { distDir } from '#dirs';
|
package/dist/experimental.mjs
CHANGED
|
@@ -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.
|
|
3
|
+
import { $ as $fetch, u as useTestContext } from './shared/test-utils.CtwoJP76.mjs';
|
|
4
4
|
import 'tinyexec';
|
|
5
5
|
import 'get-port-please';
|
|
6
6
|
import 'ofetch';
|
package/dist/module.mjs
CHANGED
|
@@ -279,7 +279,7 @@ function setupImportMocking() {
|
|
|
279
279
|
ctx.components = _;
|
|
280
280
|
});
|
|
281
281
|
nuxt.hook("imports:sources", (presets) => {
|
|
282
|
-
const idx = presets.findIndex((p) => p.imports
|
|
282
|
+
const idx = presets.findIndex((p) => p.imports?.includes("setInterval"));
|
|
283
283
|
if (idx !== -1) {
|
|
284
284
|
presets.splice(idx, 1);
|
|
285
285
|
}
|
package/dist/playwright.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as _playwright_test from '@playwright/test';
|
|
2
2
|
export { expect } from '@playwright/test';
|
|
3
3
|
import { Response } from 'playwright-core';
|
|
4
|
-
import { T as TestOptions$1, G as GotoOptions, b as TestHooks } from './shared/test-utils.
|
|
4
|
+
import { T as TestOptions$1, G as GotoOptions, b as TestHooks } from './shared/test-utils.20kU0tZa.mjs';
|
|
5
5
|
import '@nuxt/schema';
|
|
6
6
|
import 'tinyexec';
|
|
7
7
|
|
package/dist/playwright.mjs
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import defu from 'defu';
|
|
2
2
|
import { test as test$1 } from '@playwright/test';
|
|
3
3
|
export { expect } from '@playwright/test';
|
|
4
|
-
import { w as waitForHydration, d as createTest } from './shared/test-utils.
|
|
4
|
+
import { w as waitForHydration, d as createTest } from './shared/test-utils.CtoalVlS.mjs';
|
|
5
5
|
import 'node:path';
|
|
6
6
|
import 'ufo';
|
|
7
7
|
import 'std-env';
|
|
8
8
|
import 'consola';
|
|
9
9
|
import 'node:fs';
|
|
10
10
|
import '@nuxt/kit';
|
|
11
|
-
import { d as url } from './shared/test-utils.
|
|
11
|
+
import { d as url } from './shared/test-utils.CtwoJP76.mjs';
|
|
12
12
|
import 'pathe';
|
|
13
13
|
import '#dirs';
|
|
14
14
|
import 'tinyexec';
|
|
@@ -36,26 +36,51 @@ export async function setupWindow(win, environmentOptions) {
|
|
|
36
36
|
app.id = rootId;
|
|
37
37
|
win.document.body.appendChild(app);
|
|
38
38
|
const h3App = createApp();
|
|
39
|
-
if (!win.fetch) {
|
|
39
|
+
if (!win.fetch || !("Request" in win)) {
|
|
40
40
|
await import("node-fetch-native/polyfill");
|
|
41
41
|
win.URLSearchParams = globalThis.URLSearchParams;
|
|
42
|
+
win.Request ??= class Request extends globalThis.Request {
|
|
43
|
+
constructor(input, init) {
|
|
44
|
+
if (typeof input === "string") {
|
|
45
|
+
super(new URL(input, win.location.origin), init);
|
|
46
|
+
} else {
|
|
47
|
+
super(input, init);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
42
51
|
}
|
|
43
52
|
const nodeHandler = toNodeListener(h3App);
|
|
44
53
|
const registry = /* @__PURE__ */ new Set();
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
const _fetch = fetch;
|
|
55
|
+
win.fetch = async (input, _init) => {
|
|
56
|
+
let url;
|
|
57
|
+
let init = _init;
|
|
58
|
+
if (typeof input === "string") {
|
|
59
|
+
url = input;
|
|
60
|
+
} else if (input instanceof URL) {
|
|
61
|
+
url = input.toString();
|
|
62
|
+
} else {
|
|
63
|
+
url = input.url;
|
|
64
|
+
init = {
|
|
65
|
+
method: init?.method ?? input.method,
|
|
66
|
+
body: init?.body ?? input.body,
|
|
67
|
+
headers: init?.headers ?? input.headers
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const base = url.split("?")[0];
|
|
71
|
+
if (registry.has(base) || registry.has(url)) {
|
|
72
|
+
url = "/_" + url;
|
|
55
73
|
}
|
|
56
|
-
|
|
74
|
+
if (url.startsWith("/")) {
|
|
75
|
+
const response = await fetchNodeRequestHandler(nodeHandler, url, init);
|
|
76
|
+
return normalizeFetchResponse(response);
|
|
77
|
+
}
|
|
78
|
+
return _fetch(input, _init);
|
|
57
79
|
};
|
|
58
80
|
win.$fetch = createFetch({ fetch: win.fetch, Headers: win.Headers });
|
|
81
|
+
win.$fetch.create = (options = {}) => {
|
|
82
|
+
return createFetch({ fetch: win.fetch, Headers: win.Headers, ...options });
|
|
83
|
+
};
|
|
59
84
|
win.__registry = registry;
|
|
60
85
|
win.__app = h3App;
|
|
61
86
|
const timestamp = Date.now();
|
|
@@ -67,6 +67,7 @@ declare function mockComponent<PropsOptions extends Readonly<ComponentPropsOptio
|
|
|
67
67
|
|
|
68
68
|
type MountSuspendedOptions<T> = ComponentMountingOptions<T> & {
|
|
69
69
|
route?: RouteLocationRaw;
|
|
70
|
+
scoped?: boolean;
|
|
70
71
|
};
|
|
71
72
|
type SetupState$1 = Record<string, any>;
|
|
72
73
|
/**
|
|
@@ -98,6 +99,9 @@ type SetupState$1 = Record<string, any>;
|
|
|
98
99
|
declare function mountSuspended<T>(component: T, options?: MountSuspendedOptions<T>): Promise<ReturnType<typeof mount<T>> & {
|
|
99
100
|
setupState: SetupState$1;
|
|
100
101
|
}>;
|
|
102
|
+
declare global {
|
|
103
|
+
var __cleanup: Array<() => void> | undefined;
|
|
104
|
+
}
|
|
101
105
|
|
|
102
106
|
type RenderOptions<C = unknown> = RenderOptions$1<C> & {
|
|
103
107
|
route?: RouteLocationRaw;
|
|
@@ -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,
|
|
3
|
+
import { reactive, h as h$1, Suspense, nextTick, effectScope, unref, isReadonly, getCurrentInstance, isRef, 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';
|
|
@@ -87,16 +87,50 @@ async function mountSuspended(component, options) {
|
|
|
87
87
|
route = "/",
|
|
88
88
|
..._options
|
|
89
89
|
} = options || {};
|
|
90
|
+
for (const cleanupFunction of globalThis.__cleanup || []) {
|
|
91
|
+
cleanupFunction();
|
|
92
|
+
}
|
|
90
93
|
const vueApp = tryUseNuxtApp()?.vueApp || globalThis.__unctx__.get("nuxt-app").tryUse().vueApp;
|
|
91
94
|
const { render, setup, data, computed, methods } = component;
|
|
92
95
|
let setupContext;
|
|
93
96
|
let setupState;
|
|
94
97
|
const setProps = reactive({});
|
|
98
|
+
let interceptedEmit = null;
|
|
99
|
+
function getInterceptedEmitFunction(emit) {
|
|
100
|
+
if (emit !== interceptedEmit) {
|
|
101
|
+
interceptedEmit = interceptedEmit ?? ((event, ...args) => {
|
|
102
|
+
emit(event, ...args);
|
|
103
|
+
setupContext.emit(event, ...args);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return interceptedEmit;
|
|
107
|
+
}
|
|
108
|
+
function interceptEmitOnCurrentInstance() {
|
|
109
|
+
const currentInstance = getCurrentInstance();
|
|
110
|
+
if (!currentInstance) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
currentInstance.emit = getInterceptedEmitFunction(currentInstance.emit);
|
|
114
|
+
}
|
|
95
115
|
let passedProps;
|
|
116
|
+
let componentScope = null;
|
|
96
117
|
const wrappedSetup = async (props2, setupContext2) => {
|
|
118
|
+
interceptEmitOnCurrentInstance();
|
|
97
119
|
passedProps = props2;
|
|
98
120
|
if (setup) {
|
|
99
|
-
|
|
121
|
+
let result;
|
|
122
|
+
if (options?.scoped) {
|
|
123
|
+
componentScope = effectScope();
|
|
124
|
+
globalThis.__cleanup ||= [];
|
|
125
|
+
globalThis.__cleanup.push(() => {
|
|
126
|
+
componentScope?.stop();
|
|
127
|
+
});
|
|
128
|
+
result = await componentScope?.run(async () => {
|
|
129
|
+
return await setup(props2, setupContext2);
|
|
130
|
+
});
|
|
131
|
+
} else {
|
|
132
|
+
result = await setup(props2, setupContext2);
|
|
133
|
+
}
|
|
100
134
|
setupState = result && typeof result === "object" ? result : {};
|
|
101
135
|
return result;
|
|
102
136
|
}
|
|
@@ -107,11 +141,24 @@ async function mountSuspended(component, options) {
|
|
|
107
141
|
{
|
|
108
142
|
setup: (props2, ctx) => {
|
|
109
143
|
setupContext = ctx;
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
144
|
+
if (options?.scoped) {
|
|
145
|
+
const scope = effectScope();
|
|
146
|
+
globalThis.__cleanup ||= [];
|
|
147
|
+
globalThis.__cleanup.push(() => {
|
|
148
|
+
scope.stop();
|
|
149
|
+
});
|
|
150
|
+
return scope.run(() => NuxtRoot.setup(props2, {
|
|
151
|
+
...ctx,
|
|
152
|
+
expose: () => {
|
|
153
|
+
}
|
|
154
|
+
}));
|
|
155
|
+
} else {
|
|
156
|
+
return NuxtRoot.setup(props2, {
|
|
157
|
+
...ctx,
|
|
158
|
+
expose: () => {
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
115
162
|
},
|
|
116
163
|
render: (renderContext) => h$1(
|
|
117
164
|
Suspense,
|
|
@@ -130,20 +177,11 @@ async function mountSuspended(component, options) {
|
|
|
130
177
|
async setup() {
|
|
131
178
|
const router = useRouter();
|
|
132
179
|
await router.replace(route);
|
|
133
|
-
let interceptedEmit = null;
|
|
134
180
|
const clonedComponent = {
|
|
135
181
|
name: "MountSuspendedComponent",
|
|
136
182
|
...component,
|
|
137
183
|
render: render ? function(_ctx, ...args) {
|
|
138
|
-
|
|
139
|
-
if (currentInstance && currentInstance.emit !== interceptedEmit) {
|
|
140
|
-
const oldEmit = currentInstance.emit;
|
|
141
|
-
interceptedEmit = (event, ...args2) => {
|
|
142
|
-
oldEmit(event, ...args2);
|
|
143
|
-
setupContext.emit(event, ...args2);
|
|
144
|
-
};
|
|
145
|
-
currentInstance.emit = interceptedEmit;
|
|
146
|
-
}
|
|
184
|
+
interceptEmitOnCurrentInstance();
|
|
147
185
|
if (data && typeof data === "function") {
|
|
148
186
|
const dataObject = data();
|
|
149
187
|
for (const key in dataObject) {
|
|
@@ -187,7 +225,7 @@ async function mountSuspended(component, options) {
|
|
|
187
225
|
}
|
|
188
226
|
return render.call(this, renderContext, ...args);
|
|
189
227
|
} : void 0,
|
|
190
|
-
setup:
|
|
228
|
+
setup: (props2) => wrappedSetup(props2, setupContext)
|
|
191
229
|
};
|
|
192
230
|
return () => h$1(clonedComponent, { ...props, ...setProps, ...attrs }, slots);
|
|
193
231
|
}
|
|
@@ -232,6 +270,9 @@ function wrappedMountedWrapper(wrapper) {
|
|
|
232
270
|
if (prop === "element") {
|
|
233
271
|
const component = target.findComponent({ name: "MountSuspendedComponent" });
|
|
234
272
|
return component[prop];
|
|
273
|
+
} else if (prop === "vm") {
|
|
274
|
+
const vm = Reflect.get(target, prop, receiver);
|
|
275
|
+
return createVMProxy(vm, wrapper.setupState);
|
|
235
276
|
} else {
|
|
236
277
|
return Reflect.get(target, prop, receiver);
|
|
237
278
|
}
|
|
@@ -247,6 +288,28 @@ function wrappedMountedWrapper(wrapper) {
|
|
|
247
288
|
}
|
|
248
289
|
return proxy;
|
|
249
290
|
}
|
|
291
|
+
function createVMProxy(vm, setupState) {
|
|
292
|
+
return new Proxy(vm, {
|
|
293
|
+
get(target, key, receiver) {
|
|
294
|
+
const value = Reflect.get(target, key, receiver);
|
|
295
|
+
if (setupState && typeof setupState === "object" && key in setupState) {
|
|
296
|
+
return unref(setupState[key]);
|
|
297
|
+
}
|
|
298
|
+
return value;
|
|
299
|
+
},
|
|
300
|
+
set(target, key, value, receiver) {
|
|
301
|
+
if (setupState && typeof setupState === "object" && key in setupState) {
|
|
302
|
+
const setupValue = setupState[key];
|
|
303
|
+
if (setupValue && isRef(setupValue)) {
|
|
304
|
+
setupValue.value = value;
|
|
305
|
+
return true;
|
|
306
|
+
}
|
|
307
|
+
return Reflect.set(setupState, key, value, receiver);
|
|
308
|
+
}
|
|
309
|
+
return Reflect.set(target, key, value, receiver);
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
}
|
|
250
313
|
|
|
251
314
|
const WRAPPER_EL_ID = "test-wrapper";
|
|
252
315
|
async function renderSuspended(component, options) {
|
|
@@ -262,12 +325,30 @@ async function renderSuspended(component, options) {
|
|
|
262
325
|
const { render, setup, data, computed, methods } = component;
|
|
263
326
|
let setupContext;
|
|
264
327
|
let setupState;
|
|
328
|
+
let interceptedEmit = null;
|
|
329
|
+
function getInterceptedEmitFunction(emit) {
|
|
330
|
+
if (emit !== interceptedEmit) {
|
|
331
|
+
interceptedEmit = interceptedEmit ?? ((event, ...args) => {
|
|
332
|
+
emit(event, ...args);
|
|
333
|
+
setupContext.emit(event, ...args);
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
return interceptedEmit;
|
|
337
|
+
}
|
|
338
|
+
function interceptEmitOnCurrentInstance() {
|
|
339
|
+
const currentInstance = getCurrentInstance();
|
|
340
|
+
if (!currentInstance) {
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
currentInstance.emit = getInterceptedEmitFunction(currentInstance.emit);
|
|
344
|
+
}
|
|
265
345
|
for (const fn of window.__cleanup || []) {
|
|
266
346
|
fn();
|
|
267
347
|
}
|
|
268
348
|
document.querySelector(`#${WRAPPER_EL_ID}`)?.remove();
|
|
269
349
|
let passedProps;
|
|
270
350
|
const wrappedSetup = async (props2, setupContext2) => {
|
|
351
|
+
interceptEmitOnCurrentInstance();
|
|
271
352
|
passedProps = props2;
|
|
272
353
|
if (setup) {
|
|
273
354
|
const result = await setup(props2, setupContext2);
|
|
@@ -322,6 +403,7 @@ async function renderSuspended(component, options) {
|
|
|
322
403
|
name: "RenderSuspendedComponent",
|
|
323
404
|
...component,
|
|
324
405
|
render: render ? function(_ctx, ...args) {
|
|
406
|
+
interceptEmitOnCurrentInstance();
|
|
325
407
|
if (data && typeof data === "function") {
|
|
326
408
|
const dataObject = data();
|
|
327
409
|
for (const key in dataObject) {
|
|
@@ -365,7 +447,7 @@ async function renderSuspended(component, options) {
|
|
|
365
447
|
}
|
|
366
448
|
return render.call(this, renderContext, ...args);
|
|
367
449
|
} : void 0,
|
|
368
|
-
setup:
|
|
450
|
+
setup: (props2) => wrappedSetup(props2, setupContext)
|
|
369
451
|
};
|
|
370
452
|
return () => h$1(clonedComponent, { ...props && typeof props === "object" ? props : {}, ...attrs }, slots);
|
|
371
453
|
}
|
|
@@ -29,41 +29,41 @@ interface TestOptions {
|
|
|
29
29
|
fixture: string;
|
|
30
30
|
/**
|
|
31
31
|
* Name of the configuration file.
|
|
32
|
-
* @default
|
|
32
|
+
* @default 'nuxt.config'
|
|
33
33
|
*/
|
|
34
34
|
configFile: string;
|
|
35
35
|
/**
|
|
36
36
|
* Path to a directory with a Nuxt app to be put under test.
|
|
37
|
-
* @default
|
|
37
|
+
* @default '.'
|
|
38
38
|
*/
|
|
39
39
|
rootDir: string;
|
|
40
40
|
buildDir: string;
|
|
41
41
|
nuxtConfig: NuxtConfig;
|
|
42
42
|
/**
|
|
43
43
|
* Whether to run a separate build step.
|
|
44
|
-
* @default
|
|
44
|
+
* @default true // (`false` if `browser` or `server` is disabled, or if a `host` is provided)
|
|
45
45
|
*/
|
|
46
46
|
build: boolean;
|
|
47
47
|
dev: boolean;
|
|
48
48
|
/**
|
|
49
49
|
* The amount of time (in milliseconds) to allow for `setupTest` to complete its work (which could include building or generating files for a Nuxt application, depending on the options that are passed).
|
|
50
|
-
* @default
|
|
50
|
+
* @default 120000 // or `240000` on windows
|
|
51
51
|
*/
|
|
52
52
|
setupTimeout: number;
|
|
53
53
|
/**
|
|
54
54
|
* The amount of time (in milliseconds) to allow tearing down the test environment, such as closing the browser.
|
|
55
|
-
* @default
|
|
55
|
+
* @default 30000
|
|
56
56
|
*/
|
|
57
57
|
teardownTimeout: number;
|
|
58
58
|
waitFor: number;
|
|
59
59
|
/**
|
|
60
60
|
* Under the hood, Nuxt test utils uses [`playwright`](https://playwright.dev) to carry out browser testing. If this option is set, a browser will be launched and can be controlled in the subsequent test suite.
|
|
61
|
-
* @default
|
|
61
|
+
* @default false
|
|
62
62
|
*/
|
|
63
63
|
browser: boolean;
|
|
64
64
|
/**
|
|
65
65
|
* Specify the runner for the test suite. One of `'vitest' | 'jest' | 'cucumber' | 'bun'`.
|
|
66
|
-
* @default
|
|
66
|
+
* @default 'vitest'
|
|
67
67
|
*/
|
|
68
68
|
runner: TestRunner;
|
|
69
69
|
logLevel: number;
|
|
@@ -75,17 +75,17 @@ interface TestOptions {
|
|
|
75
75
|
};
|
|
76
76
|
/**
|
|
77
77
|
* Whether to launch a server to respond to requests in the test suite.
|
|
78
|
-
* @default
|
|
78
|
+
* @default true // (`false` if a `host` is provided)
|
|
79
79
|
*/
|
|
80
80
|
server: boolean;
|
|
81
81
|
/**
|
|
82
82
|
* If provided, a URL to use as the test target instead of building and running a new server. Useful for running "real" end-to-end tests against a deployed version of your application, or against an already running local server.
|
|
83
|
-
* @default
|
|
83
|
+
* @default undefined
|
|
84
84
|
*/
|
|
85
85
|
host?: string;
|
|
86
86
|
/**
|
|
87
87
|
* If provided, set the launched test server port to the value.
|
|
88
|
-
* @default
|
|
88
|
+
* @default undefined
|
|
89
89
|
*/
|
|
90
90
|
port?: number;
|
|
91
91
|
env?: StartServerOptions['env'];
|
|
@@ -109,7 +109,7 @@ interface TestHooks {
|
|
|
109
109
|
afterAll: () => Promise<void>;
|
|
110
110
|
beforeAll: () => Promise<void>;
|
|
111
111
|
/**
|
|
112
|
-
* @deprecated use `beforeAll`
|
|
112
|
+
* @deprecated use `beforeAll` instead
|
|
113
113
|
*/
|
|
114
114
|
setup: () => Promise<void>;
|
|
115
115
|
ctx: TestContext;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { u as useTestContext, d as url, c as createTestContext, a as startServer, b as stopServer, s as setTestContext } from './test-utils.
|
|
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';
|
|
2
2
|
import { existsSync, promises } from 'node:fs';
|
|
3
3
|
import { resolve } from 'node:path';
|
|
4
4
|
import { defu } from 'defu';
|
|
@@ -59,7 +59,7 @@ async function waitForHydration(page, url2, waitUntil) {
|
|
|
59
59
|
|
|
60
60
|
const kit = _kit.default || _kit;
|
|
61
61
|
const isNuxtApp = (dir) => {
|
|
62
|
-
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")));
|
|
62
|
+
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
63
|
};
|
|
64
64
|
const resolveRootDir = () => {
|
|
65
65
|
const { options } = useTestContext();
|
|
@@ -14,7 +14,7 @@ function createTestContext(options) {
|
|
|
14
14
|
fixture: "fixture",
|
|
15
15
|
configFile: "nuxt.config",
|
|
16
16
|
setupTimeout: isWindows ? 24e4 : 12e4,
|
|
17
|
-
teardownTimeout: 3e4,
|
|
17
|
+
teardownTimeout: isWindows ? 6e4 : 3e4,
|
|
18
18
|
dev: !!JSON.parse(process.env.NUXT_TEST_DEV || "false"),
|
|
19
19
|
logLevel: 1,
|
|
20
20
|
server: true,
|
|
@@ -41,26 +41,51 @@ async function setupWindow(win, environmentOptions) {
|
|
|
41
41
|
app.id = rootId;
|
|
42
42
|
win.document.body.appendChild(app);
|
|
43
43
|
const h3App = createApp();
|
|
44
|
-
if (!win.fetch) {
|
|
44
|
+
if (!win.fetch || !("Request" in win)) {
|
|
45
45
|
await import('node-fetch-native/polyfill');
|
|
46
46
|
win.URLSearchParams = globalThis.URLSearchParams;
|
|
47
|
+
win.Request ??= class Request extends globalThis.Request {
|
|
48
|
+
constructor(input, init) {
|
|
49
|
+
if (typeof input === "string") {
|
|
50
|
+
super(new URL(input, win.location.origin), init);
|
|
51
|
+
} else {
|
|
52
|
+
super(input, init);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
47
56
|
}
|
|
48
57
|
const nodeHandler = toNodeListener(h3App);
|
|
49
58
|
const registry = /* @__PURE__ */ new Set();
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
const _fetch = fetch;
|
|
60
|
+
win.fetch = async (input, _init) => {
|
|
61
|
+
let url;
|
|
62
|
+
let init = _init;
|
|
63
|
+
if (typeof input === "string") {
|
|
64
|
+
url = input;
|
|
65
|
+
} else if (input instanceof URL) {
|
|
66
|
+
url = input.toString();
|
|
67
|
+
} else {
|
|
68
|
+
url = input.url;
|
|
69
|
+
init = {
|
|
70
|
+
method: init?.method ?? input.method,
|
|
71
|
+
body: init?.body ?? input.body,
|
|
72
|
+
headers: init?.headers ?? input.headers
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const base = url.split("?")[0];
|
|
76
|
+
if (registry.has(base) || registry.has(url)) {
|
|
77
|
+
url = "/_" + url;
|
|
60
78
|
}
|
|
61
|
-
|
|
79
|
+
if (url.startsWith("/")) {
|
|
80
|
+
const response = await fetchNodeRequestHandler(nodeHandler, url, init);
|
|
81
|
+
return normalizeFetchResponse(response);
|
|
82
|
+
}
|
|
83
|
+
return _fetch(input, _init);
|
|
62
84
|
};
|
|
63
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
|
+
};
|
|
64
89
|
win.__registry = registry;
|
|
65
90
|
win.__app = h3App;
|
|
66
91
|
const timestamp = Date.now();
|
|
@@ -150,10 +175,11 @@ const jsdom = (async function(global, { jsdom = {} }) {
|
|
|
150
175
|
console: false,
|
|
151
176
|
cookieJar: false
|
|
152
177
|
});
|
|
178
|
+
const virtualConsole = jsdomOptions.console && global.console ? new VirtualConsole() : void 0;
|
|
153
179
|
const window = new JSDOM(jsdomOptions.html, {
|
|
154
180
|
...jsdomOptions,
|
|
155
181
|
resources: jsdomOptions.resources ?? (jsdomOptions.userAgent ? new ResourceLoader({ userAgent: jsdomOptions.userAgent }) : void 0),
|
|
156
|
-
virtualConsole:
|
|
182
|
+
virtualConsole: virtualConsole ? "sendTo" in virtualConsole ? virtualConsole.sendTo(global.console) : virtualConsole.forwardTo(global.console) : void 0,
|
|
157
183
|
cookieJar: jsdomOptions.cookieJar ? new CookieJar() : void 0
|
|
158
184
|
}).window;
|
|
159
185
|
window.scrollTo = () => {
|
|
@@ -161,6 +187,7 @@ const jsdom = (async function(global, { jsdom = {} }) {
|
|
|
161
187
|
return {
|
|
162
188
|
window,
|
|
163
189
|
teardown() {
|
|
190
|
+
window.close();
|
|
164
191
|
}
|
|
165
192
|
};
|
|
166
193
|
});
|
|
@@ -184,21 +211,15 @@ const index = {
|
|
|
184
211
|
jsdom: { url }
|
|
185
212
|
}));
|
|
186
213
|
if (environmentOptions?.nuxt?.mock?.intersectionObserver) {
|
|
187
|
-
win.IntersectionObserver
|
|
188
|
-
observe() {
|
|
189
|
-
}
|
|
190
|
-
unobserve() {
|
|
191
|
-
}
|
|
192
|
-
disconnect() {
|
|
193
|
-
}
|
|
194
|
-
};
|
|
214
|
+
win.IntersectionObserver ||= IntersectionObserver;
|
|
195
215
|
}
|
|
196
216
|
if (environmentOptions?.nuxt?.mock?.indexedDb) {
|
|
197
217
|
win.indexedDB = indexedDB;
|
|
198
218
|
}
|
|
199
219
|
const teardownWindow = await setupWindow(win, environmentOptions);
|
|
200
220
|
const { keys, originals } = populateGlobal(global, win, {
|
|
201
|
-
bindFunctions: true
|
|
221
|
+
bindFunctions: true,
|
|
222
|
+
additionalKeys: ["fetch", "Request"]
|
|
202
223
|
});
|
|
203
224
|
return {
|
|
204
225
|
// called after all tests with this env have been run
|
|
@@ -206,10 +227,24 @@ const index = {
|
|
|
206
227
|
keys.forEach((key) => delete global[key]);
|
|
207
228
|
teardownWindow();
|
|
208
229
|
originals.forEach((v, k) => global[k] = v);
|
|
230
|
+
if (!global.IntersectionObserver) {
|
|
231
|
+
global.IntersectionObserver = IntersectionObserver;
|
|
232
|
+
}
|
|
209
233
|
teardown();
|
|
210
234
|
}
|
|
211
235
|
};
|
|
212
236
|
}
|
|
213
237
|
};
|
|
238
|
+
class IntersectionObserver {
|
|
239
|
+
observe() {
|
|
240
|
+
}
|
|
241
|
+
unobserve() {
|
|
242
|
+
}
|
|
243
|
+
disconnect() {
|
|
244
|
+
}
|
|
245
|
+
takeRecords() {
|
|
246
|
+
return [];
|
|
247
|
+
}
|
|
248
|
+
}
|
|
214
249
|
|
|
215
250
|
export { index as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuxt/test-utils",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.20.1",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/nuxt/test-utils.git"
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
"scripts": {
|
|
57
57
|
"lint": "eslint .",
|
|
58
58
|
"lint:fix": "eslint . --fix",
|
|
59
|
+
"test": "pnpm test:types && pnpm test:unit && pnpm test:examples",
|
|
59
60
|
"test:examples": "pnpm --filter '!example-app-cucumber' --filter '!example-app-jest' -r test && pnpm --filter example-app-cucumber -r test",
|
|
60
61
|
"test:knip": "knip",
|
|
61
62
|
"test:engines": "pnpm installed-check --no-workspaces --ignore-dev",
|
|
@@ -66,72 +67,72 @@
|
|
|
66
67
|
"dev:prepare": "nuxt prepare && unbuild --stub && pnpm -r dev:prepare"
|
|
67
68
|
},
|
|
68
69
|
"dependencies": {
|
|
69
|
-
"@nuxt/kit": "^
|
|
70
|
-
"c12": "^3.
|
|
70
|
+
"@nuxt/kit": "^4.1.3",
|
|
71
|
+
"c12": "^3.3.1",
|
|
71
72
|
"consola": "^3.4.2",
|
|
72
73
|
"defu": "^6.1.4",
|
|
73
74
|
"destr": "^2.0.5",
|
|
74
75
|
"estree-walker": "^3.0.3",
|
|
75
|
-
"fake-indexeddb": "^6.
|
|
76
|
-
"get-port-please": "^3.
|
|
77
|
-
"h3": "^1.15.
|
|
78
|
-
"local-pkg": "^1.1.
|
|
79
|
-
"magic-string": "^0.30.
|
|
80
|
-
"node-fetch-native": "^1.6.
|
|
81
|
-
"node-mock-http": "^1.0.
|
|
76
|
+
"fake-indexeddb": "^6.2.4",
|
|
77
|
+
"get-port-please": "^3.2.0",
|
|
78
|
+
"h3": "^1.15.4",
|
|
79
|
+
"local-pkg": "^1.1.2",
|
|
80
|
+
"magic-string": "^0.30.19",
|
|
81
|
+
"node-fetch-native": "^1.6.7",
|
|
82
|
+
"node-mock-http": "^1.0.3",
|
|
82
83
|
"ofetch": "^1.4.1",
|
|
83
84
|
"pathe": "^2.0.3",
|
|
84
|
-
"perfect-debounce": "^
|
|
85
|
+
"perfect-debounce": "^2.0.0",
|
|
85
86
|
"radix3": "^1.1.2",
|
|
86
87
|
"scule": "^1.3.0",
|
|
87
|
-
"std-env": "^3.
|
|
88
|
+
"std-env": "^3.10.0",
|
|
88
89
|
"tinyexec": "^1.0.1",
|
|
89
90
|
"ufo": "^1.6.1",
|
|
90
|
-
"unplugin": "^2.3.
|
|
91
|
+
"unplugin": "^2.3.10",
|
|
91
92
|
"vitest-environment-nuxt": "^1.0.1",
|
|
92
|
-
"vue": "^3.5.
|
|
93
|
+
"vue": "^3.5.22"
|
|
93
94
|
},
|
|
94
95
|
"devDependencies": {
|
|
95
|
-
"@cucumber/cucumber": "
|
|
96
|
-
"@jest/globals": "30.0
|
|
97
|
-
"@nuxt/devtools-kit": "2.6.
|
|
98
|
-
"@nuxt/eslint-config": "1.
|
|
99
|
-
"@nuxt/schema": "
|
|
100
|
-
"@playwright/test": "1.
|
|
96
|
+
"@cucumber/cucumber": "12.2.0",
|
|
97
|
+
"@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",
|
|
101
102
|
"@testing-library/vue": "8.1.0",
|
|
102
|
-
"@types/bun": "1.
|
|
103
|
+
"@types/bun": "1.3.0",
|
|
103
104
|
"@types/estree": "1.0.8",
|
|
104
|
-
"@types/jsdom": "
|
|
105
|
+
"@types/jsdom": "27.0.0",
|
|
105
106
|
"@types/node": "latest",
|
|
106
|
-
"@types/semver": "7.7.
|
|
107
|
+
"@types/semver": "7.7.1",
|
|
107
108
|
"@vue/test-utils": "2.4.6",
|
|
108
|
-
"changelogen": "0.6.
|
|
109
|
+
"changelogen": "0.6.2",
|
|
109
110
|
"compatx": "0.2.0",
|
|
110
|
-
"eslint": "9.
|
|
111
|
+
"eslint": "9.38.0",
|
|
111
112
|
"installed-check": "9.3.0",
|
|
112
|
-
"knip": "5.
|
|
113
|
-
"nitropack": "2.
|
|
114
|
-
"nuxt": "
|
|
115
|
-
"pkg-pr-new": "0.0.
|
|
116
|
-
"playwright-core": "1.
|
|
117
|
-
"rollup": "4.
|
|
118
|
-
"semver": "7.7.
|
|
119
|
-
"typescript": "5.
|
|
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",
|
|
119
|
+
"semver": "7.7.3",
|
|
120
|
+
"typescript": "5.9.3",
|
|
120
121
|
"unbuild": "latest",
|
|
121
|
-
"unimport": "5.
|
|
122
|
-
"vite": "7.
|
|
122
|
+
"unimport": "5.5.0",
|
|
123
|
+
"vite": "7.1.11",
|
|
123
124
|
"vitest": "3.2.4",
|
|
124
|
-
"vue-router": "4.
|
|
125
|
-
"vue-tsc": "
|
|
125
|
+
"vue-router": "4.6.3",
|
|
126
|
+
"vue-tsc": "3.1.1"
|
|
126
127
|
},
|
|
127
128
|
"peerDependencies": {
|
|
128
|
-
"@cucumber/cucumber": "^10.3.1 ||
|
|
129
|
-
"@jest/globals": "^29.5.0 ||
|
|
129
|
+
"@cucumber/cucumber": "^10.3.1 || >=11.0.0",
|
|
130
|
+
"@jest/globals": "^29.5.0 || >=30.0.0",
|
|
130
131
|
"@playwright/test": "^1.43.1",
|
|
131
132
|
"@testing-library/vue": "^7.0.0 || ^8.0.1",
|
|
132
133
|
"@vue/test-utils": "^2.4.2",
|
|
133
|
-
"happy-dom": "
|
|
134
|
-
"jsdom": "
|
|
134
|
+
"happy-dom": "*",
|
|
135
|
+
"jsdom": "*",
|
|
135
136
|
"playwright-core": "^1.43.1",
|
|
136
137
|
"vitest": "^3.2.0"
|
|
137
138
|
},
|
|
@@ -168,27 +169,31 @@
|
|
|
168
169
|
}
|
|
169
170
|
},
|
|
170
171
|
"resolutions": {
|
|
171
|
-
"@cucumber/cucumber": "
|
|
172
|
-
"@nuxt/kit": "^
|
|
173
|
-
"@nuxt/schema": "
|
|
172
|
+
"@cucumber/cucumber": "12.2.0",
|
|
173
|
+
"@nuxt/kit": "^4.1.3",
|
|
174
|
+
"@nuxt/schema": "4.1.3",
|
|
174
175
|
"@nuxt/test-utils": "workspace:*",
|
|
175
|
-
"@types/node": "22.
|
|
176
|
-
"rollup": "4.
|
|
177
|
-
"vite": "7.
|
|
176
|
+
"@types/node": "22.18.8",
|
|
177
|
+
"rollup": "4.52.5",
|
|
178
|
+
"vite": "7.1.11",
|
|
178
179
|
"vite-node": "3.2.4",
|
|
179
180
|
"vitest": "3.2.4",
|
|
180
|
-
"vue": "^3.5.
|
|
181
|
+
"vue": "^3.5.22"
|
|
181
182
|
},
|
|
182
183
|
"engines": {
|
|
183
|
-
"node": "^
|
|
184
|
+
"node": "^20.0.0 || ^22.0.0 || >=24.0.0"
|
|
184
185
|
},
|
|
185
|
-
"packageManager": "pnpm@10.
|
|
186
|
+
"packageManager": "pnpm@10.18.3",
|
|
186
187
|
"pnpm": {
|
|
187
188
|
"onlyBuiltDependencies": [
|
|
189
|
+
"@tailwindcss/oxide",
|
|
188
190
|
"better-sqlite3"
|
|
189
191
|
],
|
|
190
192
|
"ignoredBuiltDependencies": [
|
|
191
|
-
"esbuild"
|
|
193
|
+
"esbuild",
|
|
194
|
+
"oxc-resolver",
|
|
195
|
+
"unrs-resolver",
|
|
196
|
+
"vue-demi"
|
|
192
197
|
]
|
|
193
198
|
}
|
|
194
199
|
}
|