Files
crewli/apps/app/vitest.config.ts
bert.hausmans 93e4fe398b feat(lint): enforce definePage layout meta on pages-v2
Adds a custom ESLint rule (local-rules/require-v2-layout-meta) that
fails any src/pages-v2/**.vue page missing
definePage({ meta: { layout: 'OrganizerLayoutV2' } }) (or PortalLayoutV2
under pages-v2/portal), preventing a silent wrong-shell fallback to the
default layout (RFC-WS-GUI-REDESIGN AD-G2). Wires eslint-plugin-local-rules
+ a pages-v2 override. The RuleTester spec is called at top level (ESLint
RuleTester self-manages describe/it under Vitest) and vitest.config.ts
gains the eslint-rules test glob so the spec is discovered.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 11:30:03 +02:00

86 lines
3.0 KiB
TypeScript

import { fileURLToPath } from 'node:url'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import { defineConfig } from 'vitest/config'
// Two projects share one config:
//
// - "unit" — pure-logic tests under tests/unit/ + src/**/__tests__/.
// No Vuetify, no SCSS plugin, happy-dom only. Fast path.
// - "component" — component / integration / a11y tests under tests/component/,
// tests/integration/, tests/a11y/. Loads CSS imports so
// `import '@/styles/tokens/_timetable.css'` resolves and
// getComputedStyle() returns var(--tt-…) values in jsdom.
//
// Both share the same alias map and AutoImport bag so test paths and the
// auto-imported `ref/computed/watch` etc. work identically.
const sharedAliases = {
'@': fileURLToPath(new URL('./src', import.meta.url)),
'@core': fileURLToPath(new URL('./src/@core', import.meta.url)),
'@layouts': fileURLToPath(new URL('./src/@layouts', import.meta.url)),
'@images': fileURLToPath(new URL('./src/assets/images/', import.meta.url)),
'@styles': fileURLToPath(new URL('./src/assets/styles/', import.meta.url)),
}
const sharedAutoImport = AutoImport({
imports: ['vue', '@vueuse/core', 'vue-router'],
dirs: ['./src/@core/utils', './src/@core/composable/', './src/composables/', './src/utils/'],
vueTemplate: true,
dts: false,
})
export default defineConfig({
test: {
projects: [
{
plugins: [vue(), sharedAutoImport],
resolve: { alias: sharedAliases },
test: {
name: 'unit',
environment: 'happy-dom',
globals: true,
include: [
'tests/unit/**/*.{test,spec}.ts',
'tests/*.{test,spec}.ts',
'src/**/__tests__/**/*.{test,spec}.ts',
'eslint-rules/**/__tests__/**/*.{test,spec}.ts',
],
setupFiles: ['./tests/setup.ts'],
},
},
{
plugins: [vue(), sharedAutoImport],
resolve: { alias: sharedAliases },
// Inline Vuetify so its ESM bits are processed by Vite's transform.
ssr: { noExternal: ['vuetify'] },
test: {
name: 'component',
environment: 'jsdom',
globals: true,
include: [
'tests/component/**/*.{test,spec}.ts',
'tests/integration/**/*.{test,spec}.ts',
'tests/a11y/**/*.{test,spec}.ts',
],
// Intentionally NOT including ./tests/setup.ts — it stubs `vue-router`
// globally for the unit project, which would defeat the real router
// wired by mountWithVuexy. setup.component.ts handles its own
// crypto/JSDOM stubs.
setupFiles: ['./tests/setup.component.ts'],
// CSS @import statements (e.g. `@/styles/tokens/_timetable.css`)
// need to actually load so getComputedStyle resolves CSS variables.
css: true,
server: {
deps: {
inline: ['vuetify'],
},
},
},
},
],
},
})