Set up frontend test infrastructure

Install @testing-library/react, @testing-library/jest-dom,
@testing-library/user-event, and jsdom. Configure Vitest with globals,
jsdom environment, and a setup file importing jest-dom matchers. Add a
custom render helper wrapping components with QueryClientProvider and
MemoryRouter. Exclude e2e/ from vitest. Smoke test covers
formatEvolutionMethod.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-21 13:35:15 +01:00
parent ee5bf03f19
commit c80d7d0802
9 changed files with 948 additions and 13 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -29,10 +29,14 @@
"@axe-core/playwright": "4.11.1",
"@playwright/test": "1.58.2",
"@tailwindcss/vite": "4.1.18",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "^14.6.1",
"@types/node": "24.10.10",
"@types/react": "19.2.11",
"@types/react-dom": "19.2.3",
"@vitejs/plugin-react": "5.1.3",
"jsdom": "^28.1.0",
"oxfmt": "0.33.0",
"oxlint": "1.48.0",
"tailwindcss": "4.1.18",

View File

@@ -0,0 +1 @@
import '@testing-library/jest-dom'

View File

@@ -0,0 +1,29 @@
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { render, type RenderOptions } from '@testing-library/react'
import { type ReactElement } from 'react'
import { MemoryRouter } from 'react-router-dom'
export function createTestQueryClient(): QueryClient {
return new QueryClient({
defaultOptions: {
queries: { retry: false, gcTime: Infinity },
mutations: { retry: false },
},
})
}
function AllProviders({ children }: { children: React.ReactNode }) {
const queryClient = createTestQueryClient()
return (
<QueryClientProvider client={queryClient}>
<MemoryRouter>{children}</MemoryRouter>
</QueryClientProvider>
)
}
function customRender(ui: ReactElement, options?: Omit<RenderOptions, 'wrapper'>) {
return render(ui, { wrapper: AllProviders, ...options })
}
export * from '@testing-library/react'
export { customRender as render }

View File

@@ -0,0 +1,51 @@
import { formatEvolutionMethod } from './formatEvolution'
const base = { minLevel: null, item: null, heldItem: null, condition: null }
describe('formatEvolutionMethod', () => {
it('formats level-up with a min level', () => {
expect(formatEvolutionMethod({ ...base, trigger: 'level-up', minLevel: 16 })).toBe('Level 16')
})
it('formats level-up without a min level', () => {
expect(formatEvolutionMethod({ ...base, trigger: 'level-up' })).toBe('Level up')
})
it('formats use-item trigger', () => {
expect(formatEvolutionMethod({ ...base, trigger: 'use-item', item: 'fire-stone' })).toBe(
'Fire Stone'
)
})
it('formats trade trigger', () => {
expect(formatEvolutionMethod({ ...base, trigger: 'trade' })).toBe('Trade')
})
it('formats unknown trigger by capitalizing words', () => {
expect(formatEvolutionMethod({ ...base, trigger: 'shed-skin' })).toBe('Shed Skin')
})
it('appends held item', () => {
expect(formatEvolutionMethod({ ...base, trigger: 'trade', heldItem: 'metal-coat' })).toBe(
'Trade, holding Metal Coat'
)
})
it('appends condition', () => {
expect(
formatEvolutionMethod({ ...base, trigger: 'level-up', minLevel: 20, condition: 'at night' })
).toBe('Level 20, at night')
})
it('combines all parts', () => {
expect(
formatEvolutionMethod({
trigger: 'level-up',
minLevel: 25,
item: null,
heldItem: 'kings-rock',
condition: 'high friendship',
})
).toBe('Level 25, holding Kings Rock, high friendship')
})
})

View File

@@ -5,7 +5,7 @@
"useDefineForClassFields": true,
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"module": "ESNext",
"types": ["vite/client"],
"types": ["vite/client", "vitest/globals", "@testing-library/jest-dom"],
"skipLibCheck": true,
/* Bundler mode */

View File

@@ -8,6 +8,9 @@ export default defineConfig({
plugins: [react(), tailwindcss()],
test: {
environment: 'jsdom',
globals: true,
setupFiles: ['./src/test/setup.ts'],
exclude: ['**/node_modules/**', '**/e2e/**'],
},
server: {
proxy: {