Both comments in apps/app/playwright/index.ts (header block lines 38-45 and inline at line 66) state that the Vuetify provider gets replaced by PrimeVue in F3. This predates the RFC clarification that test-runtime flip is F5, not F3 (per ARCH-TESTING.md §7). F3 builds the PrimeVue runtime in main.ts but keeps the test runtime on Vuetify. Component tests continue to mount with the Vuetify provider until F5 deliberately swaps it. This commit aligns the comments with that decision so no future contributor wonders whether the F3 sprint should have touched this file. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
126 lines
4.6 KiB
TypeScript
126 lines
4.6 KiB
TypeScript
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<string, string>,
|
|
// routes?: RouteRecordRaw[],
|
|
// piniaInitialState?: Record<string, Record<string, unknown>>,
|
|
// // 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<string, string>
|
|
routes?: RouteRecordRaw[]
|
|
piniaInitialState?: Record<string, Record<string, unknown>>
|
|
}
|
|
|
|
const defaultTheme: ThemeDefinition = {
|
|
dark: false,
|
|
colors: {
|
|
primary: '#1f7ad1',
|
|
error: '#d63d4b',
|
|
success: '#2fa66a',
|
|
warning: '#e0992c',
|
|
info: '#1f7ad1',
|
|
},
|
|
}
|
|
|
|
beforeMount<HooksConfig>(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: '<div data-test="ct-route-root" />' } },
|
|
{ path: '/:pathMatch(.*)*', component: { template: '<div data-test="ct-route-catchall" />' } },
|
|
]
|
|
|
|
const router = createRouter({ history: createMemoryHistory(), routes })
|
|
|
|
app.use(router)
|
|
|
|
if (hooksConfig?.initialRoute) {
|
|
await router.push({
|
|
path: hooksConfig.initialRoute,
|
|
query: hooksConfig.initialQuery,
|
|
})
|
|
}
|
|
await router.isReady()
|
|
})
|