import { beforeMount } from '@playwright/experimental-ct-vue/hooks' import { createPinia, setActivePinia } from 'pinia' import { QueryClient, VueQueryPlugin } from '@tanstack/vue-query' import { type RouteRecordRaw, createMemoryHistory, createRouter } from 'vue-router' import { type ThemeDefinition, createVuetify } from 'vuetify' // vuetify/components namespace import: required to register the full // component set on a freshly-created Vuetify instance per test, mirroring // tests/utils/mountWithVuexy.ts. Test infra only. import * as components from 'vuetify/components' // eslint-disable-line no-restricted-imports import * as directives from 'vuetify/directives' // Vuetify base styles — required for v-btn / v-chip / v-card etc. to // render with their actual visual appearance (not a default browser // look). Without this, Playwright visual baselines would capture // unstyled components. Removed in F3 alongside the Vuetify plugin. import 'vuetify/styles' // Plain-CSS token sheet — getComputedStyle(el).getPropertyValue('--tt-status-…') // resolves during component tests. Path resolved by the alias map in // playwright-ct.config.ts. import '@/styles/tokens/_timetable.css' // ============================================================================= // HOOKS CONFIG (per-test, opt-in) // ============================================================================= // // Tests pass `hooksConfig` to mount() to override defaults. Shape: // { // initialRoute?: string, // initialQuery?: Record, // routes?: RouteRecordRaw[], // piniaInitialState?: Record>, // // injected by mountWithProviders.ts wrapper: // notificationMockKey?: string, // } // // Defaults below render every component with the full Vuexy/Vuetify // stack. F5 (test-runtime flip) replaces the Vuetify plugin line // here with PrimeVue and updates the sanity test — that is a ~2-hour // swap, not a rewrite. Vuetify is INTENTIONAL TEMPORARY STATE in this // file; do not abstract behind a "UI framework provider" indirection // because the abstraction would itself need to be removed in F5. // See dev-docs/ARCH-TESTING.md §7 for the migration timeline. // ============================================================================= export interface HooksConfig { initialRoute?: string initialQuery?: Record routes?: RouteRecordRaw[] piniaInitialState?: Record> } const defaultTheme: ThemeDefinition = { dark: false, colors: { primary: '#1f7ad1', error: '#d63d4b', success: '#2fa66a', warning: '#e0992c', info: '#1f7ad1', }, } beforeMount(async ({ app, hooksConfig }) => { // ---- Vuetify (TEMPORARY: replaced by PrimeVue in F5) ----------------- const vuetify = createVuetify({ components, directives, theme: { defaultTheme: 'crewliLight', themes: { crewliLight: defaultTheme } }, }) app.use(vuetify) // ---- Pinia ---------------------------------------------------------- // Fresh instance per test. We do NOT use @pinia/testing's // createTestingPinia here because it depends on Vitest's `vi.fn`, // which doesn't exist in Playwright's Node runtime. Tests that need // to assert on store actions should snapshot store state via // page.evaluate() against window.__pinia (exposed below). const pinia = createPinia() app.use(pinia) setActivePinia(pinia) if (hooksConfig?.piniaInitialState) { // Hydrate store state directly. Stores are created lazily on first // use(); pre-hydration via pinia.state.value is safe. pinia.state.value = { ...pinia.state.value, ...hooksConfig.piniaInitialState, } } // Expose pinia on window for cross-frame state assertions. ;(globalThis as { __pinia?: typeof pinia }).__pinia = pinia // ---- TanStack Vue Query --------------------------------------------- const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false, refetchOnWindowFocus: false }, mutations: { retry: false }, }, }) app.use(VueQueryPlugin, { queryClient }) // ---- Router (memory history; no auth guards) ------------------------ const routes: RouteRecordRaw[] = hooksConfig?.routes ?? [ { path: '/', component: { template: '
' } }, { path: '/:pathMatch(.*)*', component: { template: '
' } }, ] const router = createRouter({ history: createMemoryHistory(), routes }) app.use(router) if (hooksConfig?.initialRoute) { await router.push({ path: hooksConfig.initialRoute, query: hooksConfig.initialQuery, }) } await router.isReady() })