Files
crewli/apps/app/vitest.config.ts
bert.hausmans 3b255a36de feat(events): add Programma tab to EventTabsNav for timetable access
The timetable canvas page at /events/{event}/timetable was added in
RFC-TIMETABLE Session 4 but had no UI entry point. EventTabsNav now
exposes it as the "Programma" tab between Artiesten and Briefings on
flat events, and between Artiesten and Briefings on festivals (in the
re-ordered tab list, post-Artiesten / pre-Briefings).

Changes:
- baseTabs gains the Programma entry at position 6 (after Artiesten).
- The festival re-order computed switches from positional indexing
  (baseTabs[5], [6], [7]) to name-based lookup via a findTab helper —
  insertions to baseTabs no longer break the festival branch.
- Icon: tabler-calendar-time. Conservative Dutch label "Programma" —
  doesn't collide with "Programmaonderdelen" (the festival sub-events
  page) since festivals see both tabs side-by-side.

vitest.config.ts: extend the component-project AutoImport to include
'vue-router' so tests of components that auto-import useRoute/useRouter
mount cleanly. (EventTabsNav was the first such test.)

tests/component/EventTabsNav.test.ts (NEW, 4 assertions):
- Programma tab is rendered with the correct label
- it carries the tabler-calendar-time icon
- the route binding resolves to the events-id-timetable name with the
  /events/.../timetable URL pattern
- the tab is also visible on a festival (re-ordered tab list path)

Mocks the useEvents composables so the component skips its skeleton/
error branches and renders tabs immediately.

Test count: 385 → 389.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-05-09 08:58:22 +02:00

85 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',
],
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'],
},
},
},
},
],
},
})