2bdbf5fbc3fdd0e2d2b86c9258ad1ce885e310d1
There was no test runner. This adds vitest with @testing-library/react and jsdom, a `test` job in CI, and the first 51 tests. They start where the audit's most user-visible defect lived. C1: every multiplayer mode started a game through startGameFromVersus, which never created a backend session, so `score` was only ever set inside `if (sessionId)` and the completion modal spun on "Calculating score..." forever, with no way out and an opponent waiting on the other side. The store tests pin the repaired path end to end - a multiplayer start creates a session, closing the loop lands on a score or a visible error, never the silent null - along with the generation guard that keeps a slow session from game A out of game B, and the serialised undo. The chain-validation hook is covered in both its server-validated and anonymous client-side forms. Coverage thresholds of 90 on every metric are codified in vite.config.ts. Two files are tested, at 100%/97.9% and 100%/91.4% branches, so `npm run test:cov` fails honestly on the whole-tree number while CI runs the plain `npm test`; the gap is real and is the next frontend work. The tests intercept the axios client rather than the API modules. An early version mocked `@/api/games` directly and one test sent a real request to the development backend: a second concurrent dynamic `import()` of a mocked aliased module resolved to the real file under vitest. The client is imported statically, which vitest mocks reliably, and the routing carries a tripwire that fails loudly on any unrouted request so a bypass can never reach the network again. Addresses L1.
React + TypeScript + Vite
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
Currently, two official plugins are available:
- @vitejs/plugin-react uses Babel (or oxc when used in rolldown-vite) for Fast Refresh
- @vitejs/plugin-react-swc uses SWC for Fast Refresh
React Compiler
The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see this documentation.
Expanding the ESLint configuration
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
// Other configs...
// Remove tseslint.configs.recommended and replace with this
tseslint.configs.recommendedTypeChecked,
// Alternatively, use this for stricter rules
tseslint.configs.strictTypeChecked,
// Optionally, add this for stylistic rules
tseslint.configs.stylisticTypeChecked,
// Other configs...
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])
You can also install eslint-plugin-react-x and eslint-plugin-react-dom for React-specific lint rules:
// eslint.config.js
import reactX from 'eslint-plugin-react-x'
import reactDom from 'eslint-plugin-react-dom'
export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
// Other configs...
// Enable lint rules for React
reactX.configs['recommended-typescript'],
// Enable lint rules for React DOM
reactDom.configs.recommended,
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])
Languages
TypeScript
97.7%
CSS
0.8%
JavaScript
0.7%
Shell
0.4%
Dockerfile
0.2%
Other
0.2%