tim
How to test Nuxt 3 Nitro Server endpoints and middlewares (avoiding defineEventHandler not defined)
vitest.config.ts:
import { defineVitestConfig } from '@nuxt/test-utils/config';
import { loadEnv } from 'vite';
export default defineVitestConfig({
test: {
env: loadEnv('test', process.cwd()),
environment: 'nuxt',
environmentOptions: {
nuxt: {
mock: {
intersectionObserver: true,
indexedDb: true,
},
},
},
coverage: {
provider: 'istanbul',
reporter: ['text', 'json', 'html'],
reportsDirectory: './coverage',
all: true,
include: ['**/*.{ts,vue}'],
exclude: ['node_modules/', 'tests/'],
},
},
});
import { defineVitestConfig } from '@nuxt/test-utils/config';
import { loadEnv } from 'vite';
export default defineVitestConfig({
test: {
env: loadEnv('test', process.cwd()),
environment: 'nuxt',
environmentOptions: {
nuxt: {
mock: {
intersectionObserver: true,
indexedDb: true,
},
},
},
coverage: {
provider: 'istanbul',
reporter: ['text', 'json', 'html'],
reportsDirectory: './coverage',
all: true,
include: ['**/*.{ts,vue}'],
exclude: ['node_modules/', 'tests/'],
},
},
});
10 replies
How to test Nuxt 3 Nitro Server endpoints and middlewares (avoiding defineEventHandler not defined)
package.json:
{
"name": "website",
"version": "v2025.3.1-dev",
"type": "module",
"private": true,
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare",
"preinstall": "npx only-allow pnpm",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"test:unit": "vitest",
"test:watch": "vitest --watch",
"test:coverage": "vitest run --coverage",
"lhci:mobile": "lhci autorun",
"lhci:desktop": "lhci autorun --collect.settings.preset=desktop"
},
"engines": {
"node": ">=18.18.0",
"npm": ">=9.7.0"
},
"dependencies": {
"@headlessui/vue": "^1.7.23",
"@heroicons/vue": "^2.2.0",
"@nuxt/devtools": "latest",
"@nuxt/types": "^2.18.1",
"@nuxtjs/i18n": "^9.2.1",
"@nuxtjs/tailwindcss": "^6.12.2",
"@nuxtjs/turnstile": "^0.9.11",
"@tailwindcss/aspect-ratio": "^0.4.2",
"@tailwindcss/forms": "^0.5.9",
"@tailwindcss/typography": "^0.5.15",
"@types/node": "^22.13.9",
"@vueuse/core": "^12.7.0",
"motion-v": "0.10.1",
"nuxt-cloudflare-analytics": "^1.0.8",
"nuxt-headlessui": "^1.2.0",
"nuxt-security": "2.1.5",
"resend": "4.1.2"
},
"devDependencies": {
"@inspira-ui/plugins": "^0.0.1",
"@lhci/cli": "^0.14.0",
"@nuxt/eslint": "^1.0.1",
"@nuxt/scripts": "^0.10.4",
"@nuxt/test-utils": "^3.17.1",
"@nuxtjs/apollo": "5.0.0-alpha.14",
"@nuxtjs/supabase": "^1.4.4",
"@vitest/coverage-istanbul": "^3.0.3",
"@vue/test-utils": "^2.4.6",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"eslint": "^9.20.1",
"happy-dom": "^17.1.9",
"nuxt": "^3.14.1592",
"playwright-core": "^1.49.1",
"tailwind-merge": "^3.0.1",
"tailwindcss-animate": "^1.0.7",
"vitest": "^3.0.3"
}
}
{
"name": "website",
"version": "v2025.3.1-dev",
"type": "module",
"private": true,
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare",
"preinstall": "npx only-allow pnpm",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"test:unit": "vitest",
"test:watch": "vitest --watch",
"test:coverage": "vitest run --coverage",
"lhci:mobile": "lhci autorun",
"lhci:desktop": "lhci autorun --collect.settings.preset=desktop"
},
"engines": {
"node": ">=18.18.0",
"npm": ">=9.7.0"
},
"dependencies": {
"@headlessui/vue": "^1.7.23",
"@heroicons/vue": "^2.2.0",
"@nuxt/devtools": "latest",
"@nuxt/types": "^2.18.1",
"@nuxtjs/i18n": "^9.2.1",
"@nuxtjs/tailwindcss": "^6.12.2",
"@nuxtjs/turnstile": "^0.9.11",
"@tailwindcss/aspect-ratio": "^0.4.2",
"@tailwindcss/forms": "^0.5.9",
"@tailwindcss/typography": "^0.5.15",
"@types/node": "^22.13.9",
"@vueuse/core": "^12.7.0",
"motion-v": "0.10.1",
"nuxt-cloudflare-analytics": "^1.0.8",
"nuxt-headlessui": "^1.2.0",
"nuxt-security": "2.1.5",
"resend": "4.1.2"
},
"devDependencies": {
"@inspira-ui/plugins": "^0.0.1",
"@lhci/cli": "^0.14.0",
"@nuxt/eslint": "^1.0.1",
"@nuxt/scripts": "^0.10.4",
"@nuxt/test-utils": "^3.17.1",
"@nuxtjs/apollo": "5.0.0-alpha.14",
"@nuxtjs/supabase": "^1.4.4",
"@vitest/coverage-istanbul": "^3.0.3",
"@vue/test-utils": "^2.4.6",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"eslint": "^9.20.1",
"happy-dom": "^17.1.9",
"nuxt": "^3.14.1592",
"playwright-core": "^1.49.1",
"tailwind-merge": "^3.0.1",
"tailwindcss-animate": "^1.0.7",
"vitest": "^3.0.3"
}
}
10 replies
How to test Nuxt 3 Nitro Server endpoints and middlewares (avoiding defineEventHandler not defined)
and thats my test file (
tests/unit/server/middleware/visibilityGuard.global.spec.ts
):
import { describe, it, expect, vi, beforeEach } from 'vitest';
import type { H3Event, EventHandlerRequest } from 'h3';
import { sendRedirect } from 'h3';
import visibilityGuard from '../../../../server/middleware/visibilityGuard.global';
vi.stubGlobal('defineEventHandler', (handler: any) => handler);
const runtimeConfigMock = vi.fn(() => ({ APP_STATE: 'maintenance' }));
vi.stubGlobal('useRuntimeConfig', runtimeConfigMock);
vi.mock('h3', async () => {
return {
sendRedirect: vi.fn(),
};
});
describe('visibilityGuard global middleware', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('should be a function', () => {
expect(typeof visibilityGuard).toBe('function');
});
const createEvent = (path: string): H3Event<EventHandlerRequest> => ({
path,
context: {}, // Mock necessary context
} as unknown as H3Event<EventHandlerRequest>);
it('redirects to /maintenance when app state is maintenance and path is not /maintenance', () => {
runtimeConfigMock.mockReturnValueOnce({ APP_STATE: 'maintenance' });
const event = createEvent('/dashboard');
visibilityGuard(event);
expect(sendRedirect).toHaveBeenCalledWith(event, '/maintenance');
});
// more test cases
it('does nothing (allows navigation) when app state is development', () => {
runtimeConfigMock.mockReturnValueOnce({ APP_STATE: 'development' });
const event = createEvent('/dashboard');
visibilityGuard(event);
expect(sendRedirect).not.toHaveBeenCalled();
});
});
import { describe, it, expect, vi, beforeEach } from 'vitest';
import type { H3Event, EventHandlerRequest } from 'h3';
import { sendRedirect } from 'h3';
import visibilityGuard from '../../../../server/middleware/visibilityGuard.global';
vi.stubGlobal('defineEventHandler', (handler: any) => handler);
const runtimeConfigMock = vi.fn(() => ({ APP_STATE: 'maintenance' }));
vi.stubGlobal('useRuntimeConfig', runtimeConfigMock);
vi.mock('h3', async () => {
return {
sendRedirect: vi.fn(),
};
});
describe('visibilityGuard global middleware', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('should be a function', () => {
expect(typeof visibilityGuard).toBe('function');
});
const createEvent = (path: string): H3Event<EventHandlerRequest> => ({
path,
context: {}, // Mock necessary context
} as unknown as H3Event<EventHandlerRequest>);
it('redirects to /maintenance when app state is maintenance and path is not /maintenance', () => {
runtimeConfigMock.mockReturnValueOnce({ APP_STATE: 'maintenance' });
const event = createEvent('/dashboard');
visibilityGuard(event);
expect(sendRedirect).toHaveBeenCalledWith(event, '/maintenance');
});
// more test cases
it('does nothing (allows navigation) when app state is development', () => {
runtimeConfigMock.mockReturnValueOnce({ APP_STATE: 'development' });
const event = createEvent('/dashboard');
visibilityGuard(event);
expect(sendRedirect).not.toHaveBeenCalled();
});
});
10 replies
How to test Nuxt 3 Nitro Server endpoints and middlewares (avoiding defineEventHandler not defined)
thats my middleware (
server/middleware/visibilityGuard.global.ts
):
import type { EventHandlerRequest, H3Event } from 'h3';
import type { NitroRuntimeConfig } from 'nitropack';
import { sendRedirect } from 'h3';
export default defineEventHandler((event: H3Event<EventHandlerRequest>) => {
const runtimeConfig: NitroRuntimeConfig = useRuntimeConfig(event);
const appState: string = runtimeConfig.APP_STATE || 'maintenance';
switch (appState) {
case 'development':
break;
case 'production':
if (event.path === '/maintenance' || event.path === '/coming-soon') {
return sendRedirect(event, '/');
}
break;
case 'coming':
if (event.path !== '/coming-soon') {
return sendRedirect(event, '/coming-soon');
}
break;
case 'maintenance':
if (event.path !== '/maintenance') {
return sendRedirect(event, '/maintenance');
}
break;
default:
break;
}
});
import type { EventHandlerRequest, H3Event } from 'h3';
import type { NitroRuntimeConfig } from 'nitropack';
import { sendRedirect } from 'h3';
export default defineEventHandler((event: H3Event<EventHandlerRequest>) => {
const runtimeConfig: NitroRuntimeConfig = useRuntimeConfig(event);
const appState: string = runtimeConfig.APP_STATE || 'maintenance';
switch (appState) {
case 'development':
break;
case 'production':
if (event.path === '/maintenance' || event.path === '/coming-soon') {
return sendRedirect(event, '/');
}
break;
case 'coming':
if (event.path !== '/coming-soon') {
return sendRedirect(event, '/coming-soon');
}
break;
case 'maintenance':
if (event.path !== '/maintenance') {
return sendRedirect(event, '/maintenance');
}
break;
default:
break;
}
});
10 replies
Nuxt 3.12.1 Update: Prerender Error with app.use Function
Oh luckily, I already feared that the configuration should have been more fine-grained and that I had made mistakes that would only stop the startup with the new version, but that reassures me, then it goes back to the old version for now. Thank you very much!
9 replies
Nuxt 3.12.1 Update: Prerender Error with app.use Function
This was the initial (500) error:
This is the latest (500) error:
message-compiler.mjs:94 Uncaught (in promise) SyntaxError: Need to install with `app.use` function (at message-compiler.mjs:94:19)
at createCompileError (message-compiler.mjs:94:19)
at createI18nError (vue-i18n.mjs:103:12)
at useI18n (vue-i18n.mjs:2325:15)
at setup (app.vue:13:40)
at callWithErrorHandling (runtime-core.esm-bundler.js:195:19)
at setupStatefulComponent (runtime-core.esm-bundler.js:7630:25)
at setupComponent (runtime-core.esm-bundler.js:7591:36)
at mountComponent (runtime-core.esm-bundler.js:5917:7)
at processComponent (runtime-core.esm-bundler.js:5883:9)
at patch (runtime-core.esm-bundler.js:5351:11)
message-compiler.mjs:94 Uncaught (in promise) SyntaxError: Need to install with `app.use` function (at message-compiler.mjs:94:19)
at createCompileError (message-compiler.mjs:94:19)
at createI18nError (vue-i18n.mjs:103:12)
at useI18n (vue-i18n.mjs:2325:15)
at setup (app.vue:13:40)
at callWithErrorHandling (runtime-core.esm-bundler.js:195:19)
at setupStatefulComponent (runtime-core.esm-bundler.js:7630:25)
at setupComponent (runtime-core.esm-bundler.js:7591:36)
at mountComponent (runtime-core.esm-bundler.js:5917:7)
at processComponent (runtime-core.esm-bundler.js:5883:9)
at patch (runtime-core.esm-bundler.js:5351:11)
[nuxt] error caught during app initialization TypeError: Cannot destructure property 'url' of 'config' as it is undefined.
at setup (supabase.client.mjs:11:13)
at client.mjs:35:36
at executeAsync (index.mjs:111:19)
at setup (client.mjs:35:36)
at nuxt.js:137:60
at fn (nuxt.js:214:44)
at Object.runWithContext (runtime-core.esm-bundler.js:3980:18)
at callWithNuxt (nuxt.js:220:24)
at nuxt.js:37:41
at EffectScope.run (reactivity.esm-bundler.js:43:16)
[nuxt] error caught during app initialization TypeError: Cannot destructure property 'url' of 'config' as it is undefined.
at setup (supabase.client.mjs:11:13)
at client.mjs:35:36
at executeAsync (index.mjs:111:19)
at setup (client.mjs:35:36)
at nuxt.js:137:60
at fn (nuxt.js:214:44)
at Object.runWithContext (runtime-core.esm-bundler.js:3980:18)
at callWithNuxt (nuxt.js:220:24)
at nuxt.js:37:41
at EffectScope.run (reactivity.esm-bundler.js:43:16)
9 replies