@nuxt/test-utils 3.23.0 → 4.0.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/README.md +3 -0
- package/dist/config.d.mts +2 -7
- package/dist/config.mjs +32 -20
- package/dist/e2e.d.mts +2 -2
- package/dist/e2e.mjs +1 -1
- package/dist/module.d.mts +2 -2
- package/dist/module.mjs +178 -187
- package/dist/playwright.d.mts +1 -1
- package/dist/playwright.mjs +4 -3
- package/dist/runtime/browser-entry.mjs +2 -5
- package/dist/runtime/entry.mjs +4 -3
- package/dist/runtime/nuxt-root.mjs +2 -2
- package/dist/runtime/shared/environment.mjs +1 -11
- package/dist/runtime/shared/vue-wrapper-plugin.d.ts +3 -48
- package/dist/runtime/shared/vue-wrapper-plugin.mjs +7 -2
- package/dist/runtime-utils/index.d.mts +15 -1
- package/dist/runtime-utils/index.mjs +61 -17
- package/dist/shared/{test-utils.C9GKP_T5.d.mts → test-utils.BLyxqr96.d.mts} +3 -3
- package/dist/shared/{test-utils.5cnw0YZR.mjs → test-utils.E_cAGA8l.mjs} +3 -3
- package/dist/vitest-environment.d.mts +3 -3
- package/dist/vitest-environment.mjs +16 -22
- package/dist/vitest-wrapper/cli.mjs +9 -4
- package/package.json +58 -58
|
@@ -6,12 +6,12 @@ export default defineComponent({
|
|
|
6
6
|
const nuxtApp = useNuxtApp();
|
|
7
7
|
provide(PageRouteSymbol, useRoute());
|
|
8
8
|
const done = nuxtApp.deferHydration();
|
|
9
|
-
const results = nuxtApp.hooks.callHookWith((hooks) => hooks.map((hook) => hook()), "vue:setup");
|
|
9
|
+
const results = nuxtApp.hooks.callHookWith((hooks) => hooks.map((hook) => hook()), "vue:setup", []);
|
|
10
10
|
if (import.meta.dev && results && results.some((i) => i && "then" in i)) {
|
|
11
11
|
console.error("[nuxt] Error in `vue:setup`. Callbacks must be synchronous.");
|
|
12
12
|
}
|
|
13
13
|
onErrorCaptured((err, target, info) => {
|
|
14
|
-
nuxtApp.hooks.callHook("vue:error", err, target, info)
|
|
14
|
+
nuxtApp.hooks.callHook("vue:error", err, target, info)?.catch((hookError) => console.error("[nuxt] Error in `vue:error` hook", hookError));
|
|
15
15
|
if (isNuxtError(err) && (err.fatal || err.unhandled)) {
|
|
16
16
|
return false;
|
|
17
17
|
}
|
|
@@ -16,16 +16,6 @@ export async function setupWindow(win, environmentOptions) {
|
|
|
16
16
|
data: {},
|
|
17
17
|
state: {}
|
|
18
18
|
};
|
|
19
|
-
const rootId = environmentOptions.nuxt.rootId || "nuxt-test";
|
|
20
|
-
let el;
|
|
21
|
-
try {
|
|
22
|
-
el = win.document.querySelector(rootId);
|
|
23
|
-
} catch {
|
|
24
|
-
}
|
|
25
|
-
if (el) {
|
|
26
|
-
return () => {
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
19
|
const consoleInfo = console.info;
|
|
30
20
|
console.info = (...args) => {
|
|
31
21
|
if (args[0] === "<Suspense> is an experimental feature and its API will likely change.") {
|
|
@@ -34,7 +24,7 @@ export async function setupWindow(win, environmentOptions) {
|
|
|
34
24
|
return consoleInfo(...args);
|
|
35
25
|
};
|
|
36
26
|
const app = win.document.createElement("div");
|
|
37
|
-
app.id = rootId;
|
|
27
|
+
app.id = environmentOptions.nuxt.rootId || "nuxt-test";
|
|
38
28
|
win.document.body.appendChild(app);
|
|
39
29
|
if (!win.fetch || !("Request" in win)) {
|
|
40
30
|
await import("node-fetch-native/polyfill");
|
|
@@ -1,50 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
type Options = ReturnType<typeof createPluginOptions>;
|
|
3
|
-
export declare function getVueWrapperPlugin(): Options;
|
|
4
|
-
declare function createPluginOptions(): {
|
|
5
|
-
_name: string;
|
|
6
|
-
_instances: WeakRef<VueWrapper>[];
|
|
7
|
-
readonly instances: VueWrapper<unknown, {
|
|
8
|
-
$: import("vue").ComponentInternalInstance;
|
|
9
|
-
$data: {};
|
|
10
|
-
$props: {};
|
|
11
|
-
$attrs: {
|
|
12
|
-
[x: string]: unknown;
|
|
13
|
-
};
|
|
14
|
-
$refs: {
|
|
15
|
-
[x: string]: unknown;
|
|
16
|
-
};
|
|
17
|
-
$slots: Readonly<{
|
|
18
|
-
[name: string]: import("vue").Slot<any> | undefined;
|
|
19
|
-
}>;
|
|
20
|
-
$root: import("vue").ComponentPublicInstance | null;
|
|
21
|
-
$parent: import("vue").ComponentPublicInstance | null;
|
|
22
|
-
$host: Element | null;
|
|
23
|
-
$emit: (event: string, ...args: any[]) => void;
|
|
24
|
-
$el: any;
|
|
25
|
-
$options: import("vue").ComponentOptionsBase<any, any, any, any, any, any, any, any, any, {}, {}, string, {}, {}, {}, string, import("vue").ComponentProvideOptions> & {
|
|
26
|
-
beforeCreate?: (() => void) | (() => void)[];
|
|
27
|
-
created?: (() => void) | (() => void)[];
|
|
28
|
-
beforeMount?: (() => void) | (() => void)[];
|
|
29
|
-
mounted?: (() => void) | (() => void)[];
|
|
30
|
-
beforeUpdate?: (() => void) | (() => void)[];
|
|
31
|
-
updated?: (() => void) | (() => void)[];
|
|
32
|
-
activated?: (() => void) | (() => void)[];
|
|
33
|
-
deactivated?: (() => void) | (() => void)[];
|
|
34
|
-
beforeDestroy?: (() => void) | (() => void)[];
|
|
35
|
-
beforeUnmount?: (() => void) | (() => void)[];
|
|
36
|
-
destroyed?: (() => void) | (() => void)[];
|
|
37
|
-
unmounted?: (() => void) | (() => void)[];
|
|
38
|
-
renderTracked?: ((e: import("vue").DebuggerEvent) => void) | ((e: import("vue").DebuggerEvent) => void)[];
|
|
39
|
-
renderTriggered?: ((e: import("vue").DebuggerEvent) => void) | ((e: import("vue").DebuggerEvent) => void)[];
|
|
40
|
-
errorCaptured?: ((err: unknown, instance: import("vue").ComponentPublicInstance | null, info: string) => boolean | void) | ((err: unknown, instance: import("vue").ComponentPublicInstance | null, info: string) => boolean | void)[];
|
|
41
|
-
};
|
|
42
|
-
$forceUpdate: () => void;
|
|
43
|
-
$nextTick: typeof import("vue").nextTick;
|
|
44
|
-
$watch<T extends string | ((...args: any) => any)>(source: T, cb: T extends (...args: any) => infer R ? (...args: [R, R, import("@vue/reactivity").OnCleanup]) => any : (...args: [any, any, import("@vue/reactivity").OnCleanup]) => any, options?: import("vue").WatchOptions): import("vue").WatchStopHandle;
|
|
45
|
-
} & Readonly<{}> & Omit<{}, never> & import("vue").ShallowUnwrapRef<{}> & {} & import("vue").ComponentCustomProperties & {}>[];
|
|
46
|
-
addInstance(instance: VueWrapper): void;
|
|
1
|
+
interface Options {
|
|
47
2
|
hasNuxtPage(): boolean;
|
|
48
|
-
|
|
49
|
-
|
|
3
|
+
}
|
|
4
|
+
export declare function getVueWrapperPlugin(): Options;
|
|
50
5
|
export {};
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import { config } from "@vue/test-utils";
|
|
2
1
|
const PLUGIN_NAME = "nuxt-test-utils";
|
|
2
|
+
const config = await import("@vue/test-utils").then((r) => r.config).catch(() => void 0);
|
|
3
3
|
export function getVueWrapperPlugin() {
|
|
4
|
-
|
|
4
|
+
if (!config) {
|
|
5
|
+
return {
|
|
6
|
+
hasNuxtPage: () => false
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
const installed = config.plugins.VueWrapper.installedPlugins.find(({ options: options2 }) => options2?._name === PLUGIN_NAME);
|
|
5
10
|
if (installed) return installed.options;
|
|
6
11
|
const options = createPluginOptions();
|
|
7
12
|
config.plugins.VueWrapper.install((instance, options2) => {
|
|
@@ -56,9 +56,23 @@ declare function registerEndpoint(url: string, options: EventHandler | {
|
|
|
56
56
|
* }
|
|
57
57
|
* })
|
|
58
58
|
* ```
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* // Making partial mock with original implementation
|
|
62
|
+
* mockNuxtImport(useRoute, original => vi.fn(original))
|
|
63
|
+
* // or (with name based)
|
|
64
|
+
* mockNuxtImport('useRoute', original => vi.fn(original))
|
|
65
|
+
* // or (with name based, type parameter)
|
|
66
|
+
* mockNuxtImport<typeof useRoute>('useRoute', original => vi.fn(original))
|
|
67
|
+
*
|
|
68
|
+
* // Override in test
|
|
69
|
+
* vi.mocked(useRoute).mockImplementation(
|
|
70
|
+
* (...args) => ({ ...vi.mocked(useRoute).getMockImplementation()!(...args), path: '/mocked' }),
|
|
71
|
+
* )
|
|
72
|
+
* ```
|
|
59
73
|
* @see https://nuxt.com/docs/getting-started/testing#mocknuxtimport
|
|
60
74
|
*/
|
|
61
|
-
declare function mockNuxtImport<T = unknown>(_target: string | T, _factory: () => T | Promise<T>): void;
|
|
75
|
+
declare function mockNuxtImport<T = unknown>(_target: string | T, _factory: T extends string ? (original: any) => any : (original: T) => T | Promise<T>): void;
|
|
62
76
|
/**
|
|
63
77
|
* `mockComponent` allows you to mock Nuxt's component.
|
|
64
78
|
* @param path - component name in PascalCase, or the relative path of the component.
|
|
@@ -1,17 +1,31 @@
|
|
|
1
1
|
import { mount } from '@vue/test-utils';
|
|
2
|
-
import { reactive, h as h$1, Suspense, nextTick
|
|
3
|
-
import { defu } from 'defu';
|
|
2
|
+
import { reactive, h as h$1, Suspense, nextTick, getCurrentInstance, onErrorCaptured, effectScope } from 'vue';
|
|
4
3
|
import { defineComponent, useRouter, h, tryUseNuxtApp } from '#imports';
|
|
5
4
|
import NuxtRoot from '#build/root-component.mjs';
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
function getEndpointRegistry() {
|
|
7
|
+
const app = window.__app ?? {};
|
|
8
|
+
return app._registeredEndpointRegistry ||= {};
|
|
9
|
+
}
|
|
10
|
+
function findEndpointRegistryHandlers(url) {
|
|
11
|
+
const endpointRegistry = getEndpointRegistry();
|
|
12
|
+
const pathname = url.replace(/[?#].*$/, "");
|
|
13
|
+
for (const [key, handlers] of Object.entries(endpointRegistry)) {
|
|
14
|
+
if (key === url || key === pathname) {
|
|
15
|
+
if (handlers?.length) {
|
|
16
|
+
return handlers;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
8
21
|
function registerEndpoint(url, options) {
|
|
9
22
|
const app = window.__app;
|
|
10
23
|
if (!app) {
|
|
11
24
|
throw new Error("registerEndpoint() can only be used in a `@nuxt/test-utils` runtime environment");
|
|
12
25
|
}
|
|
13
|
-
const config = typeof options === "function" ? { handler: options, method: void 0, once: false } : options;
|
|
26
|
+
const config = typeof options === "function" ? { url, handler: options, method: void 0, once: false } : { ...options, url };
|
|
14
27
|
config.handler = Object.assign(config.handler, { __is_handler__: true });
|
|
28
|
+
const endpointRegistry = getEndpointRegistry();
|
|
15
29
|
endpointRegistry[url] ||= [];
|
|
16
30
|
endpointRegistry[url].push(config);
|
|
17
31
|
window.__registry.add(url);
|
|
@@ -34,16 +48,17 @@ function mockComponent(_path, _component) {
|
|
|
34
48
|
);
|
|
35
49
|
}
|
|
36
50
|
const handler = Object.assign(async (event) => {
|
|
37
|
-
const url = "url" in event && event.url ? event.url.pathname.replace(/^\/_/, "") : event.path.replace(
|
|
38
|
-
const
|
|
51
|
+
const url = "url" in event && event.url ? (event.url.pathname + event.url.search).replace(/^\/_/, "") : event.path.replace(/^\/_/, "");
|
|
52
|
+
const registeredHandlers = findEndpointRegistryHandlers(url);
|
|
53
|
+
const latestHandler = [...registeredHandlers || []].reverse().find((config) => config.method ? event.method === config.method : true);
|
|
39
54
|
if (!latestHandler) return;
|
|
40
55
|
const result = await latestHandler.handler(event);
|
|
41
56
|
if (!latestHandler.once) return result;
|
|
42
|
-
const index =
|
|
57
|
+
const index = registeredHandlers?.indexOf(latestHandler);
|
|
43
58
|
if (index === void 0 || index === -1) return result;
|
|
44
|
-
|
|
45
|
-
if (
|
|
46
|
-
window.__registry.delete(url);
|
|
59
|
+
registeredHandlers?.splice(index, 1);
|
|
60
|
+
if (registeredHandlers?.length === 0) {
|
|
61
|
+
window.__registry.delete(latestHandler.url);
|
|
47
62
|
}
|
|
48
63
|
return result;
|
|
49
64
|
}, { __is_handler__: true });
|
|
@@ -51,9 +66,10 @@ function registerGlobalHandler(app) {
|
|
|
51
66
|
app.use(handler, {
|
|
52
67
|
match: (...args) => {
|
|
53
68
|
const [eventOrPath, _event = eventOrPath] = args;
|
|
54
|
-
const url = typeof eventOrPath === "string" ? eventOrPath.replace(/^\/_/, "")
|
|
69
|
+
const url = typeof eventOrPath === "string" ? eventOrPath.replace(/^\/_/, "") : (eventOrPath.url.pathname + eventOrPath.url.search).replace(/^\/_/, "");
|
|
55
70
|
const event = _event;
|
|
56
|
-
|
|
71
|
+
const registeredHandlers = findEndpointRegistryHandlers(url);
|
|
72
|
+
return registeredHandlers?.some((config) => config.method ? event?.method === config.method : true) ?? false;
|
|
57
73
|
}
|
|
58
74
|
});
|
|
59
75
|
return true;
|
|
@@ -197,7 +213,7 @@ function wrapperSuspended(component, options, {
|
|
|
197
213
|
render: wrappedRender(() => h$1(
|
|
198
214
|
Suspense,
|
|
199
215
|
{
|
|
200
|
-
onResolve: () => nextTick
|
|
216
|
+
onResolve: () => nextTick().then(() => {
|
|
201
217
|
if (isMountSettled) return;
|
|
202
218
|
isMountSettled = true;
|
|
203
219
|
wrapper.setupState = setupState;
|
|
@@ -214,8 +230,9 @@ function wrapperSuspended(component, options, {
|
|
|
214
230
|
}
|
|
215
231
|
))
|
|
216
232
|
},
|
|
217
|
-
|
|
218
|
-
|
|
233
|
+
{
|
|
234
|
+
...wrapperFnOptions,
|
|
235
|
+
global: mergeComponentMountingGlobalOptions(wrapperFnOptions.global, {
|
|
219
236
|
config: {
|
|
220
237
|
globalProperties: makeAllPropertiesEnumerable(
|
|
221
238
|
vueApp.config.globalProperties
|
|
@@ -229,11 +246,38 @@ function wrapperSuspended(component, options, {
|
|
|
229
246
|
[ClonedComponent.name]: false
|
|
230
247
|
},
|
|
231
248
|
components: { ...vueApp._context.components, RouterLink }
|
|
232
|
-
}
|
|
233
|
-
}
|
|
249
|
+
})
|
|
250
|
+
}
|
|
234
251
|
);
|
|
235
252
|
});
|
|
236
253
|
}
|
|
254
|
+
function mergeComponentMountingGlobalOptions(options = {}, defaults = {}) {
|
|
255
|
+
return {
|
|
256
|
+
...options,
|
|
257
|
+
mixins: [...defaults.mixins || [], ...options.mixins || []],
|
|
258
|
+
stubs: {
|
|
259
|
+
...defaults.stubs,
|
|
260
|
+
...Array.isArray(options.stubs) ? Object.fromEntries(options.stubs.map((n) => [n, true])) : options.stubs
|
|
261
|
+
},
|
|
262
|
+
plugins: [...defaults.plugins || [], ...options.plugins || []],
|
|
263
|
+
components: { ...defaults.components, ...options.components },
|
|
264
|
+
provide: { ...defaults.provide, ...options.provide },
|
|
265
|
+
mocks: { ...defaults.mocks, ...options.mocks },
|
|
266
|
+
config: {
|
|
267
|
+
...defaults.config,
|
|
268
|
+
...options.config,
|
|
269
|
+
compilerOptions: {
|
|
270
|
+
...defaults.config?.compilerOptions,
|
|
271
|
+
...options.config?.compilerOptions
|
|
272
|
+
},
|
|
273
|
+
globalProperties: {
|
|
274
|
+
...defaults.config?.globalProperties,
|
|
275
|
+
...options.config?.globalProperties
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
directives: { ...defaults.directives, ...options.directives }
|
|
279
|
+
};
|
|
280
|
+
}
|
|
237
281
|
function makeAllPropertiesEnumerable(target) {
|
|
238
282
|
return {
|
|
239
283
|
...target,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Page, Response as Response$1, BrowserContextOptions, Browser, LaunchOptions } from 'playwright-core';
|
|
2
2
|
import { NuxtConfig, Nuxt } from '@nuxt/schema';
|
|
3
3
|
import { exec } from 'tinyexec';
|
|
4
4
|
import { $Fetch } from 'ofetch';
|
|
@@ -116,5 +116,5 @@ interface TestHooks {
|
|
|
116
116
|
ctx: TestContext;
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
export { $fetch as $, createBrowser as
|
|
120
|
-
export type { GotoOptions as G, NuxtPage as N, StartServerOptions as S, TestOptions as T, TestHooks as a, TestContext as b, TestRunner as
|
|
119
|
+
export { $fetch as $, createBrowser as d, createPage as e, fetch as f, getBrowser as g, stopServer as h, startServer as s, url as u, waitForHydration as w };
|
|
120
|
+
export type { GotoOptions as G, NuxtPage as N, StartServerOptions as S, TestOptions as T, TestHooks as a, TestContext as b, TestRunner as c };
|
|
@@ -117,10 +117,10 @@ async function buildFixture() {
|
|
|
117
117
|
async function setupBun(hooks) {
|
|
118
118
|
const bunTest = await import('bun:test');
|
|
119
119
|
hooks.ctx.mockFn = bunTest.mock;
|
|
120
|
-
bunTest.beforeAll(hooks.beforeAll);
|
|
120
|
+
bunTest.beforeAll(hooks.beforeAll, hooks.ctx.options.setupTimeout);
|
|
121
121
|
bunTest.beforeEach(hooks.beforeEach);
|
|
122
122
|
bunTest.afterEach(hooks.afterEach);
|
|
123
|
-
bunTest.afterAll(hooks.afterAll);
|
|
123
|
+
bunTest.afterAll(hooks.afterAll, hooks.ctx.options.teardownTimeout);
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
async function setupCucumber(hooks) {
|
|
@@ -209,4 +209,4 @@ async function setup(options = {}) {
|
|
|
209
209
|
await setupFn(hooks);
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
-
export { createPage as a, buildFixture as b, createBrowser as c, createTest as d,
|
|
212
|
+
export { createPage as a, buildFixture as b, createBrowser as c, createTest as d, setupMaps as e, getBrowser as g, loadFixture as l, setup as s, waitForHydration as w };
|
|
@@ -2,7 +2,7 @@ import { Environment } from 'vitest/environments';
|
|
|
2
2
|
import { H3Event as H3Event$1 } from 'h3';
|
|
3
3
|
import { H3Event } from 'h3-next';
|
|
4
4
|
import { $Fetch } from 'nitropack';
|
|
5
|
-
import {
|
|
5
|
+
import { EnvironmentOptions } from 'vitest/node';
|
|
6
6
|
|
|
7
7
|
declare const _default: Environment;
|
|
8
8
|
|
|
@@ -29,8 +29,8 @@ interface NuxtWindow extends Window {
|
|
|
29
29
|
Headers: typeof Headers;
|
|
30
30
|
}
|
|
31
31
|
interface EnvironmentNuxtOptions {
|
|
32
|
-
jsdom?:
|
|
33
|
-
happyDom?:
|
|
32
|
+
jsdom?: EnvironmentOptions['jsdom'];
|
|
33
|
+
happyDom?: EnvironmentOptions['happyDOM'];
|
|
34
34
|
}
|
|
35
35
|
type EnvironmentNuxt = (global: typeof globalThis, options: EnvironmentNuxtOptions) => Promise<{
|
|
36
36
|
window: NuxtWindow;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
+
import { resolveModulePath } from 'exsolve';
|
|
1
2
|
import { indexedDB } from 'fake-indexeddb';
|
|
2
3
|
import { joinURL } from 'ufo';
|
|
3
4
|
import defu from 'defu';
|
|
4
|
-
import { populateGlobal } from 'vitest/environments';
|
|
5
5
|
import { createFetch } from 'ofetch';
|
|
6
6
|
import { toRouteMatcher, createRouter, exportMatcher } from 'radix3';
|
|
7
|
-
import { importModule } from 'local-pkg';
|
|
8
7
|
|
|
9
8
|
function defineEventHandler(handler) {
|
|
10
9
|
return Object.assign(handler, { __is_handler__: true });
|
|
@@ -128,16 +127,6 @@ async function setupWindow(win, environmentOptions) {
|
|
|
128
127
|
data: {},
|
|
129
128
|
state: {}
|
|
130
129
|
};
|
|
131
|
-
const rootId = environmentOptions.nuxt.rootId || "nuxt-test";
|
|
132
|
-
let el;
|
|
133
|
-
try {
|
|
134
|
-
el = win.document.querySelector(rootId);
|
|
135
|
-
} catch {
|
|
136
|
-
}
|
|
137
|
-
if (el) {
|
|
138
|
-
return () => {
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
130
|
const consoleInfo = console.info;
|
|
142
131
|
console.info = (...args) => {
|
|
143
132
|
if (args[0] === "<Suspense> is an experimental feature and its API will likely change.") {
|
|
@@ -146,7 +135,7 @@ async function setupWindow(win, environmentOptions) {
|
|
|
146
135
|
return consoleInfo(...args);
|
|
147
136
|
};
|
|
148
137
|
const app = win.document.createElement("div");
|
|
149
|
-
app.id = rootId;
|
|
138
|
+
app.id = environmentOptions.nuxt.rootId || "nuxt-test";
|
|
150
139
|
win.document.body.appendChild(app);
|
|
151
140
|
if (!win.fetch || !("Request" in win)) {
|
|
152
141
|
await import('node-fetch-native/polyfill');
|
|
@@ -202,7 +191,7 @@ async function setupWindow(win, environmentOptions) {
|
|
|
202
191
|
}
|
|
203
192
|
|
|
204
193
|
const happyDom = (async function(_, { happyDom = {} }) {
|
|
205
|
-
const { Window, GlobalWindow } = await
|
|
194
|
+
const { Window, GlobalWindow } = await import('happy-dom');
|
|
206
195
|
const window = new (GlobalWindow || Window)(happyDom);
|
|
207
196
|
return {
|
|
208
197
|
window,
|
|
@@ -213,7 +202,7 @@ const happyDom = (async function(_, { happyDom = {} }) {
|
|
|
213
202
|
});
|
|
214
203
|
|
|
215
204
|
const jsdom = (async function(global, { jsdom = {} }) {
|
|
216
|
-
const { CookieJar, JSDOM, ResourceLoader, VirtualConsole } = await
|
|
205
|
+
const { CookieJar, JSDOM, ResourceLoader, VirtualConsole } = await import('jsdom');
|
|
217
206
|
const jsdomOptions = defu(jsdom, {
|
|
218
207
|
html: "<!DOCTYPE html>",
|
|
219
208
|
url: "http://localhost:3000",
|
|
@@ -227,7 +216,7 @@ const jsdom = (async function(global, { jsdom = {} }) {
|
|
|
227
216
|
const virtualConsole = jsdomOptions.console && global.console ? new VirtualConsole() : void 0;
|
|
228
217
|
const window = new JSDOM(jsdomOptions.html, {
|
|
229
218
|
...jsdomOptions,
|
|
230
|
-
resources: jsdomOptions.resources ?? (jsdomOptions.userAgent ? new ResourceLoader({ userAgent: jsdomOptions.userAgent }) : void 0),
|
|
219
|
+
resources: jsdomOptions.resources ?? (jsdomOptions.userAgent ? ResourceLoader ? new ResourceLoader({ userAgent: jsdomOptions.userAgent }) : { userAgent: jsdomOptions.userAgent } : void 0),
|
|
231
220
|
virtualConsole: virtualConsole ? "sendTo" in virtualConsole ? virtualConsole.sendTo(global.console) : virtualConsole.forwardTo(global.console) : void 0,
|
|
232
221
|
cookieJar: jsdomOptions.cookieJar ? new CookieJar() : void 0
|
|
233
222
|
}).window;
|
|
@@ -247,22 +236,23 @@ const environmentMap = {
|
|
|
247
236
|
};
|
|
248
237
|
const index = {
|
|
249
238
|
name: "nuxt",
|
|
250
|
-
|
|
239
|
+
viteEnvironment: "client",
|
|
251
240
|
async setup(global, environmentOptions) {
|
|
241
|
+
const { populateGlobal } = await importVitestEnvironments();
|
|
252
242
|
const url = joinURL(
|
|
253
|
-
environmentOptions?.
|
|
254
|
-
environmentOptions?.
|
|
243
|
+
environmentOptions.nuxt?.url ?? "http://localhost:3000",
|
|
244
|
+
environmentOptions.nuxtRuntimeConfig?.app?.baseURL || "/"
|
|
255
245
|
);
|
|
256
|
-
const environmentName = environmentOptions.nuxt
|
|
246
|
+
const environmentName = environmentOptions.nuxt?.domEnvironment;
|
|
257
247
|
const environment = environmentMap[environmentName] || environmentMap["happy-dom"];
|
|
258
248
|
const { window: win, teardown } = await environment(global, defu(environmentOptions, {
|
|
259
249
|
happyDom: { url },
|
|
260
250
|
jsdom: { url }
|
|
261
251
|
}));
|
|
262
|
-
if (environmentOptions
|
|
252
|
+
if (environmentOptions.nuxt?.mock?.intersectionObserver) {
|
|
263
253
|
win.IntersectionObserver ||= IntersectionObserver;
|
|
264
254
|
}
|
|
265
|
-
if (environmentOptions
|
|
255
|
+
if (environmentOptions.nuxt?.mock?.indexedDb) {
|
|
266
256
|
win.indexedDB = indexedDB;
|
|
267
257
|
}
|
|
268
258
|
const teardownWindow = await setupWindow(win, environmentOptions);
|
|
@@ -284,6 +274,10 @@ const index = {
|
|
|
284
274
|
};
|
|
285
275
|
}
|
|
286
276
|
};
|
|
277
|
+
async function importVitestEnvironments() {
|
|
278
|
+
const pkg = resolveModulePath("vitest/runtime", { try: true }) ? "vitest/runtime" : "vitest/environments";
|
|
279
|
+
return await import(pkg);
|
|
280
|
+
}
|
|
287
281
|
class IntersectionObserver {
|
|
288
282
|
observe() {
|
|
289
283
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { importModule } from 'local-pkg';
|
|
2
1
|
import { getPort } from 'get-port-please';
|
|
3
2
|
import { a as listenHostMessages, b as sendMessageToHost } from '../shared/test-utils.DDUpsMYL.mjs';
|
|
4
3
|
|
|
@@ -32,10 +31,16 @@ function createCustomReporter(onVitestInit) {
|
|
|
32
31
|
onTestRunStart() {
|
|
33
32
|
sendMessageToHost("updated", toUpdatedResult());
|
|
34
33
|
},
|
|
35
|
-
|
|
34
|
+
onTestModuleCollected() {
|
|
36
35
|
sendMessageToHost("updated", toUpdatedResult());
|
|
37
36
|
},
|
|
38
|
-
|
|
37
|
+
onTestCaseResult() {
|
|
38
|
+
sendMessageToHost("updated", toUpdatedResult());
|
|
39
|
+
},
|
|
40
|
+
onTestModuleEnd() {
|
|
41
|
+
sendMessageToHost("updated", toUpdatedResult());
|
|
42
|
+
},
|
|
43
|
+
onTestRunEnd() {
|
|
39
44
|
sendMessageToHost("finished", toFinishedResult());
|
|
40
45
|
}
|
|
41
46
|
};
|
|
@@ -50,7 +55,7 @@ async function main() {
|
|
|
50
55
|
});
|
|
51
56
|
});
|
|
52
57
|
const port = apiPorts ? await getPort({ ports: apiPorts }) : void 0;
|
|
53
|
-
const { startVitest } = await
|
|
58
|
+
const { startVitest } = await import('vitest/node');
|
|
54
59
|
const customReporter = createCustomReporter((vitest2) => {
|
|
55
60
|
listenHostMessages(async ({ type, payload }) => {
|
|
56
61
|
if (type === "stop") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuxt/test-utils",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/nuxt/test-utils.git"
|
|
@@ -57,19 +57,20 @@
|
|
|
57
57
|
"lint": "eslint .",
|
|
58
58
|
"lint:fix": "eslint . --fix",
|
|
59
59
|
"test": "pnpm test:types && pnpm test:unit && pnpm test:examples",
|
|
60
|
-
"test:examples": "pnpm --filter '!example-app-cucumber' --filter '!example-app-jest' --filter '!example-app-bun' -r test && pnpm --filter example-app-cucumber -r test",
|
|
60
|
+
"test:examples": "pnpm --filter '!@nuxt/test-utils' --filter '!example-app-cucumber' --filter '!example-app-jest' --filter '!example-app-bun' -r test && pnpm --filter example-app-cucumber -r test",
|
|
61
61
|
"test:knip": "knip",
|
|
62
62
|
"test:engines": "pnpm installed-check --no-workspaces --ignore-dev",
|
|
63
|
-
"test:types": "vue-tsc --noEmit",
|
|
64
|
-
"test:unit": "vitest test/unit --run",
|
|
63
|
+
"test:types": "vue-tsc --noEmit && vitest --dir ./test/types --typecheck.only --run",
|
|
64
|
+
"test:unit": "vitest --dir ./test/unit --run",
|
|
65
65
|
"build": "unbuild",
|
|
66
66
|
"prepack": "unbuild",
|
|
67
67
|
"dev:prepare": "nuxt prepare && unbuild --stub && pnpm -r dev:prepare"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@clack/prompts": "1.
|
|
71
|
-
"@nuxt/kit": "^
|
|
72
|
-
"
|
|
70
|
+
"@clack/prompts": "1.2.0",
|
|
71
|
+
"@nuxt/devtools-kit": "^2.7.0",
|
|
72
|
+
"@nuxt/kit": "^3.21.2",
|
|
73
|
+
"c12": "^3.3.4",
|
|
73
74
|
"consola": "^3.4.2",
|
|
74
75
|
"defu": "^6.1.4",
|
|
75
76
|
"destr": "^2.0.5",
|
|
@@ -77,70 +78,69 @@
|
|
|
77
78
|
"exsolve": "^1.0.8",
|
|
78
79
|
"fake-indexeddb": "^6.2.5",
|
|
79
80
|
"get-port-please": "^3.2.0",
|
|
80
|
-
"h3": "^1.15.
|
|
81
|
-
"h3-next": "npm:h3
|
|
81
|
+
"h3": "^1.15.11",
|
|
82
|
+
"h3-next": "npm:h3@2.0.1-rc.20",
|
|
82
83
|
"local-pkg": "^1.1.2",
|
|
83
84
|
"magic-string": "^0.30.21",
|
|
84
85
|
"node-fetch-native": "^1.6.7",
|
|
85
86
|
"node-mock-http": "^1.0.4",
|
|
86
|
-
"nypm": "^0.6.
|
|
87
|
+
"nypm": "^0.6.5",
|
|
87
88
|
"ofetch": "^1.5.1",
|
|
88
89
|
"pathe": "^2.0.3",
|
|
89
|
-
"perfect-debounce": "^2.
|
|
90
|
+
"perfect-debounce": "^2.1.0",
|
|
90
91
|
"radix3": "^1.1.2",
|
|
91
92
|
"scule": "^1.3.0",
|
|
92
|
-
"std-env": "^
|
|
93
|
-
"tinyexec": "^1.
|
|
94
|
-
"ufo": "^1.6.
|
|
95
|
-
"unplugin": "^
|
|
96
|
-
"vitest-environment-nuxt": "
|
|
97
|
-
"vue": "^3.5.
|
|
93
|
+
"std-env": "^4.0.0",
|
|
94
|
+
"tinyexec": "^1.1.1",
|
|
95
|
+
"ufo": "^1.6.3",
|
|
96
|
+
"unplugin": "^3.0.0",
|
|
97
|
+
"vitest-environment-nuxt": "workspace:*",
|
|
98
|
+
"vue": "^3.5.32"
|
|
98
99
|
},
|
|
99
100
|
"devDependencies": {
|
|
100
|
-
"@cucumber/cucumber": "12.
|
|
101
|
-
"@jest/globals": "30.
|
|
102
|
-
"@nuxt/
|
|
103
|
-
"@nuxt/
|
|
104
|
-
"@
|
|
105
|
-
"@playwright/test": "1.57.0",
|
|
101
|
+
"@cucumber/cucumber": "12.7.0",
|
|
102
|
+
"@jest/globals": "30.3.0",
|
|
103
|
+
"@nuxt/eslint-config": "1.15.2",
|
|
104
|
+
"@nuxt/schema": "4.4.2",
|
|
105
|
+
"@playwright/test": "1.59.1",
|
|
106
106
|
"@testing-library/vue": "8.1.0",
|
|
107
|
-
"@types/bun": "1.3.
|
|
107
|
+
"@types/bun": "1.3.11",
|
|
108
108
|
"@types/estree": "1.0.8",
|
|
109
|
-
"@types/jsdom": "
|
|
109
|
+
"@types/jsdom": "28.0.1",
|
|
110
110
|
"@types/node": "latest",
|
|
111
111
|
"@types/semver": "7.7.1",
|
|
112
|
-
"@vitest/browser-playwright": "4.
|
|
112
|
+
"@vitest/browser-playwright": "4.1.2",
|
|
113
113
|
"@vue/test-utils": "2.4.6",
|
|
114
114
|
"changelogen": "0.6.2",
|
|
115
115
|
"compatx": "0.2.0",
|
|
116
|
-
"eslint": "
|
|
117
|
-
"installed-check": "
|
|
118
|
-
"knip": "
|
|
119
|
-
"nitropack": "2.
|
|
120
|
-
"nuxt": "4.
|
|
121
|
-
"oxc-parser": "
|
|
122
|
-
"pkg-pr-new": "0.0.
|
|
123
|
-
"playwright-core": "1.
|
|
124
|
-
"rollup": "4.
|
|
125
|
-
"semver": "7.7.
|
|
126
|
-
"typescript": "
|
|
116
|
+
"eslint": "10.2.0",
|
|
117
|
+
"installed-check": "10.0.1",
|
|
118
|
+
"knip": "6.3.0",
|
|
119
|
+
"nitropack": "2.13.3",
|
|
120
|
+
"nuxt": "4.4.2",
|
|
121
|
+
"oxc-parser": "0.124.0",
|
|
122
|
+
"pkg-pr-new": "0.0.66",
|
|
123
|
+
"playwright-core": "1.59.1",
|
|
124
|
+
"rollup": "4.60.1",
|
|
125
|
+
"semver": "7.7.4",
|
|
126
|
+
"typescript": "6.0.2",
|
|
127
127
|
"unbuild": "latest",
|
|
128
|
-
"unimport": "
|
|
129
|
-
"vite": "
|
|
130
|
-
"vitest": "
|
|
131
|
-
"vue-router": "
|
|
132
|
-
"vue-tsc": "3.2.
|
|
128
|
+
"unimport": "6.0.2",
|
|
129
|
+
"vite": "8.0.5",
|
|
130
|
+
"vitest": "4.1.2",
|
|
131
|
+
"vue-router": "5.0.4",
|
|
132
|
+
"vue-tsc": "3.2.6"
|
|
133
133
|
},
|
|
134
134
|
"peerDependencies": {
|
|
135
|
-
"@cucumber/cucumber": "
|
|
136
|
-
"@jest/globals": "
|
|
135
|
+
"@cucumber/cucumber": ">=11.0.0",
|
|
136
|
+
"@jest/globals": ">=30.0.0",
|
|
137
137
|
"@playwright/test": "^1.43.1",
|
|
138
|
-
"@testing-library/vue": "^
|
|
138
|
+
"@testing-library/vue": "^8.0.1",
|
|
139
139
|
"@vue/test-utils": "^2.4.2",
|
|
140
|
-
"happy-dom": "
|
|
141
|
-
"jsdom": "
|
|
140
|
+
"happy-dom": ">=20.0.11",
|
|
141
|
+
"jsdom": ">=27.4.0",
|
|
142
142
|
"playwright-core": "^1.43.1",
|
|
143
|
-
"vitest": "^
|
|
143
|
+
"vitest": "^4.0.2"
|
|
144
144
|
},
|
|
145
145
|
"peerDependenciesMeta": {
|
|
146
146
|
"@cucumber/cucumber": {
|
|
@@ -175,19 +175,19 @@
|
|
|
175
175
|
}
|
|
176
176
|
},
|
|
177
177
|
"resolutions": {
|
|
178
|
-
"@cucumber/cucumber": "12.
|
|
179
|
-
"@nuxt/schema": "4.
|
|
178
|
+
"@cucumber/cucumber": "12.7.0",
|
|
179
|
+
"@nuxt/schema": "4.4.2",
|
|
180
180
|
"@nuxt/test-utils": "workspace:*",
|
|
181
|
-
"@types/node": "24.
|
|
181
|
+
"@types/node": "24.12.2",
|
|
182
182
|
"nitro": "https://pkg.pr.new/nitrojs/nitro@00598a8",
|
|
183
|
-
"rollup": "4.
|
|
184
|
-
"vite": "
|
|
185
|
-
"vite-node": "
|
|
186
|
-
"vitest": "
|
|
187
|
-
"vue": "^3.5.
|
|
183
|
+
"rollup": "4.60.1",
|
|
184
|
+
"vite": "8.0.5",
|
|
185
|
+
"vite-node": "6.0.0",
|
|
186
|
+
"vitest": "4.1.2",
|
|
187
|
+
"vue": "^3.5.32"
|
|
188
188
|
},
|
|
189
189
|
"engines": {
|
|
190
|
-
"node": "^20.
|
|
190
|
+
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
|
191
191
|
},
|
|
192
|
-
"packageManager": "pnpm@10.
|
|
192
|
+
"packageManager": "pnpm@10.33.0"
|
|
193
193
|
}
|