chess/planning/testing/testing-tools.md
Christoph Wagner 5ad0700b41 refactor: Consolidate repository structure - flatten from workspace pattern
Restructured project from nested workspace pattern to flat single-repo layout.
This eliminates redundant nesting and consolidates all project files under version control.

## Migration Summary

**Before:**
```
alex/ (workspace, not versioned)
├── chess-game/ (git repo)
│   ├── js/, css/, tests/
│   └── index.html
└── docs/ (planning, not versioned)
```

**After:**
```
alex/ (git repo, everything versioned)
├── js/, css/, tests/
├── index.html
├── docs/ (project documentation)
├── planning/ (historical planning docs)
├── .gitea/ (CI/CD)
└── CLAUDE.md (configuration)
```

## Changes Made

### Structure Consolidation
- Moved all chess-game/ contents to root level
- Removed redundant chess-game/ subdirectory
- Flattened directory structure (eliminated one nesting level)

### Documentation Organization
- Moved chess-game/docs/ → docs/ (project documentation)
- Moved alex/docs/ → planning/ (historical planning documents)
- Added CLAUDE.md (workspace configuration)
- Added IMPLEMENTATION_PROMPT.md (original project prompt)

### Version Control Improvements
- All project files now under version control
- Planning documents preserved in planning/ folder
- Merged .gitignore files (workspace + project)
- Added .claude/ agent configurations

### File Updates
- Updated .gitignore to include both workspace and project excludes
- Moved README.md to root level
- All import paths remain functional (relative paths unchanged)

## Benefits

 **Simpler Structure** - One level of nesting removed
 **Complete Versioning** - All documentation now in git
 **Standard Layout** - Matches open-source project conventions
 **Easier Navigation** - Direct access to all project files
 **CI/CD Compatible** - All workflows still functional

## Technical Validation

-  Node.js environment verified
-  Dependencies installed successfully
-  Dev server starts and responds
-  All core files present and accessible
-  Git repository functional

## Files Preserved

**Implementation Files:**
- js/ (3,517 lines of code)
- css/ (4 stylesheets)
- tests/ (87 test cases)
- index.html
- package.json

**CI/CD Pipeline:**
- .gitea/workflows/ci.yml
- .gitea/workflows/release.yml

**Documentation:**
- docs/ (12+ documentation files)
- planning/ (historical planning materials)
- README.md

**Configuration:**
- jest.config.js, babel.config.cjs, playwright.config.js
- .gitignore (merged)
- CLAUDE.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 10:05:26 +01:00

765 lines
14 KiB
Markdown

# Testing Tools and Setup Guide
## Overview
This document provides detailed instructions for setting up the testing environment and configuring all testing tools for the HTML chess game project.
---
## 1. Core Testing Framework
### 1.1 Jest
**Purpose**: JavaScript testing framework for unit and integration tests
**Installation**:
```bash
npm install --save-dev jest @types/jest
```
**Configuration** (`jest.config.js`):
```javascript
module.exports = {
// Test environment
testEnvironment: 'jsdom',
// Coverage configuration
collectCoverageFrom: [
'src/**/*.{js,jsx,ts,tsx}',
'!src/**/*.d.ts',
'!src/**/*.stories.{js,jsx,ts,tsx}',
'!src/index.{js,jsx,ts,tsx}',
],
// Coverage thresholds
coverageThresholds: {
global: {
statements: 85,
branches: 80,
functions: 85,
lines: 85,
},
'./src/chess-engine/': {
statements: 95,
branches: 90,
functions: 95,
lines: 95,
},
},
// Test match patterns
testMatch: [
'<rootDir>/tests/**/*.test.{js,jsx,ts,tsx}',
'<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}',
],
// Module paths
modulePaths: ['<rootDir>/src'],
// Setup files
setupFilesAfterEnv: ['<rootDir>/tests/setup.js'],
// Transform files
transform: {
'^.+\\.(js|jsx|ts|tsx)$': 'babel-jest',
},
// Module name mapper (for CSS/images)
moduleNameMapper: {
'\\.(css|less|scss|sass)$': 'identity-obj-proxy',
'\\.(jpg|jpeg|png|gif|svg)$': '<rootDir>/tests/__mocks__/fileMock.js',
},
// Watch plugins
watchPlugins: [
'jest-watch-typeahead/filename',
'jest-watch-typeahead/testname',
],
};
```
**Package.json Scripts**:
```json
{
"scripts": {
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand"
}
}
```
---
### 1.2 Testing Library
**Purpose**: DOM testing utilities for user-centric tests
**Installation**:
```bash
npm install --save-dev @testing-library/dom
npm install --save-dev @testing-library/user-event
```
**Setup** (`tests/setup.js`):
```javascript
import '@testing-library/jest-dom';
// Custom matchers
expect.extend({
toBeValidChessMove(received, expected) {
const pass = isValidMove(received);
return {
pass,
message: () => `Expected ${received} to be a valid chess move`,
};
},
});
// Global test utilities
global.createBoard = () => {
// Board creation helper
};
```
---
## 2. End-to-End Testing
### 2.1 Playwright
**Purpose**: Cross-browser E2E testing
**Installation**:
```bash
npm install --save-dev @playwright/test
npx playwright install
```
**Configuration** (`playwright.config.js`):
```javascript
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests/e2e',
// Timeouts
timeout: 30000,
expect: {
timeout: 5000,
},
// Retry failed tests
retries: process.env.CI ? 2 : 0,
// Parallel execution
workers: process.env.CI ? 1 : undefined,
// Reporter
reporter: [
['html', { outputFolder: 'playwright-report' }],
['junit', { outputFile: 'test-results/junit.xml' }],
],
// Shared settings
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
},
// Browser projects
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},
{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
{
name: 'Mobile Chrome',
use: { ...devices['Pixel 5'] },
},
{
name: 'Mobile Safari',
use: { ...devices['iPhone 13'] },
},
],
// Dev server
webServer: {
command: 'npm run start',
port: 3000,
reuseExistingServer: !process.env.CI,
},
});
```
**Example Test** (`tests/e2e/game-flow.spec.js`):
```javascript
import { test, expect } from '@playwright/test';
test.describe('Chess Game Flow', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/');
});
test('should play a complete game', async ({ page }) => {
// Move white pawn e2-e4
await page.dragAndDrop('[data-square="e2"]', '[data-square="e4"]');
await expect(page.locator('[data-square="e4"]')).toHaveClass(/white-pawn/);
// Move black pawn e7-e5
await page.dragAndDrop('[data-square="e7"]', '[data-square="e5"]');
// Verify turn indicator
await expect(page.locator('[data-testid="turn-indicator"]'))
.toHaveText('White to move');
});
});
```
**Scripts**:
```json
{
"scripts": {
"test:e2e": "playwright test",
"test:e2e:headed": "playwright test --headed",
"test:e2e:debug": "playwright test --debug",
"test:e2e:report": "playwright show-report"
}
}
```
---
## 3. Visual Regression Testing
### 3.1 Percy (Recommended)
**Purpose**: Automated visual testing
**Installation**:
```bash
npm install --save-dev @percy/cli @percy/playwright
```
**Configuration** (`.percy.yml`):
```yaml
version: 2
static:
include: "public/**/*"
snapshot:
widths:
- 375
- 768
- 1280
min-height: 1024
percy-css: |
.animated { animation: none !important; }
```
**Usage in Tests**:
```javascript
import { percySnapshot } from '@percy/playwright';
test('visual test - initial board', async ({ page }) => {
await page.goto('/');
await percySnapshot(page, 'Initial Board State');
});
```
---
### 3.2 Alternative: Playwright Screenshot Comparison
**Built-in screenshot testing**:
```javascript
test('visual regression - board', async ({ page }) => {
await page.goto('/');
await expect(page).toHaveScreenshot('initial-board.png', {
maxDiffPixels: 100,
});
});
```
---
## 4. Performance Testing
### 4.1 Lighthouse CI
**Installation**:
```bash
npm install --save-dev @lhci/cli
```
**Configuration** (`lighthouserc.js`):
```javascript
module.exports = {
ci: {
collect: {
startServerCommand: 'npm run start',
url: ['http://localhost:3000'],
numberOfRuns: 3,
},
assert: {
assertions: {
'categories:performance': ['error', { minScore: 0.9 }],
'categories:accessibility': ['error', { minScore: 0.9 }],
'categories:best-practices': ['error', { minScore: 0.9 }],
'categories:seo': ['error', { minScore: 0.9 }],
'first-contentful-paint': ['error', { maxNumericValue: 1500 }],
'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],
'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],
'time-to-interactive': ['error', { maxNumericValue: 3500 }],
},
},
upload: {
target: 'temporary-public-storage',
},
},
};
```
**Scripts**:
```json
{
"scripts": {
"test:perf": "lhci autorun",
"test:perf:collect": "lhci collect",
"test:perf:assert": "lhci assert"
}
}
```
---
### 4.2 Custom Performance Tests
**Using Performance API**:
```javascript
// tests/performance/move-calculation.test.js
describe('Move Calculation Performance', () => {
test('should generate legal moves in <100ms', () => {
const board = createComplexPosition();
const startTime = performance.now();
const legalMoves = generateLegalMoves(board);
const duration = performance.now() - startTime;
expect(duration).toBeLessThan(100);
expect(legalMoves.length).toBeGreaterThan(0);
});
});
```
---
## 5. Accessibility Testing
### 5.1 axe-core
**Installation**:
```bash
npm install --save-dev @axe-core/playwright
```
**Usage in Playwright**:
```javascript
import { test, expect } from '@playwright/test';
import { injectAxe, checkA11y } from '@axe-core/playwright';
test('accessibility scan', async ({ page }) => {
await page.goto('/');
await injectAxe(page);
const violations = await checkA11y(page, null, {
detailedReport: true,
detailedReportOptions: {
html: true,
},
});
expect(violations).toHaveLength(0);
});
```
---
### 5.2 pa11y
**Installation**:
```bash
npm install --save-dev pa11y
```
**Configuration** (`pa11y.config.js`):
```javascript
module.exports = {
standard: 'WCAG2AA',
runners: ['axe', 'htmlcs'],
level: 'error',
threshold: 0,
chromeLaunchConfig: {
args: ['--no-sandbox'],
},
};
```
**Script**:
```json
{
"scripts": {
"test:a11y": "pa11y http://localhost:3000 --config pa11y.config.js"
}
}
```
---
## 6. Code Quality Tools
### 6.1 ESLint
**Installation**:
```bash
npm install --save-dev eslint eslint-config-airbnb-base
```
**Configuration** (`.eslintrc.json`):
```json
{
"extends": ["airbnb-base"],
"env": {
"browser": true,
"jest": true
},
"rules": {
"no-console": "warn",
"complexity": ["error", 10],
"max-lines": ["warn", 500],
"max-depth": ["error", 4]
}
}
```
---
### 6.2 Prettier
**Installation**:
```bash
npm install --save-dev prettier eslint-config-prettier
```
**Configuration** (`.prettierrc`):
```json
{
"singleQuote": true,
"trailingComma": "all",
"printWidth": 100,
"tabWidth": 2,
"semi": true
}
```
---
### 6.3 SonarQube (Optional)
**For advanced code quality metrics**:
```bash
npm install --save-dev sonarqube-scanner
```
---
## 7. Test Data Management
### 7.1 FEN Parser
**Installation**:
```bash
npm install --save-dev chess.js
```
**Usage**:
```javascript
import { Chess } from 'chess.js';
const loadPosition = (fen) => {
const chess = new Chess(fen);
return chess;
};
// In tests
test('Fool\'s Mate', () => {
const chess = new Chess();
chess.move('f3');
chess.move('e5');
chess.move('g4');
chess.move('Qh4');
expect(chess.isCheckmate()).toBe(true);
});
```
---
### 7.2 Test Data Fixtures
**Structure**:
```
tests/
fixtures/
positions/
fools-mate.fen
scholars-mate.fen
back-rank-mate.fen
games/
immortal-game.pgn
opera-game.pgn
```
**Loading Fixtures**:
```javascript
// tests/utils/fixtures.js
import { readFileSync } from 'fs';
import { join } from 'path';
export const loadFEN = (name) => {
const path = join(__dirname, '../fixtures/positions', `${name}.fen`);
return readFileSync(path, 'utf-8').trim();
};
export const loadPGN = (name) => {
const path = join(__dirname, '../fixtures/games', `${name}.pgn`);
return readFileSync(path, 'utf-8');
};
```
---
## 8. Continuous Integration
### 8.1 GitHub Actions Workflow
**File**: `.github/workflows/test.yml`
```yaml
name: Test Suite
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
- name: Run unit tests
run: npm run test:coverage
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
files: ./coverage/lcov.info
- name: Run E2E tests
run: npm run test:e2e
- name: Upload Playwright report
if: always()
uses: actions/upload-artifact@v3
with:
name: playwright-report
path: playwright-report/
- name: Run performance tests
run: npm run test:perf
- name: Run accessibility tests
run: npm run test:a11y
```
---
### 8.2 Pre-commit Hooks
**Installation**:
```bash
npm install --save-dev husky lint-staged
npx husky install
```
**Configuration** (`.husky/pre-commit`):
```bash
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged
```
**Lint-staged** (`package.json`):
```json
{
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write",
"jest --bail --findRelatedTests"
]
}
}
```
---
## 9. Test Utilities
### 9.1 Custom Test Helpers
**File**: `tests/utils/helpers.js`
```javascript
export const createTestBoard = (fen = null) => {
// Create board from FEN or default
};
export const makeMove = (board, from, to) => {
// Helper to make moves in tests
};
export const assertCheckmate = (board) => {
// Assert checkmate state
};
export const waitForAnimation = async (element) => {
// Wait for CSS animations to complete
};
```
---
### 9.2 Mock Data Generators
```javascript
// tests/utils/generators.js
export const generateRandomPosition = () => {
// Generate valid random board position
};
export const generateLegalMoves = (position) => {
// Generate all legal moves for position
};
```
---
## 10. Monitoring and Reporting
### 10.1 Coverage Reports
**HTML Report**:
```bash
npm run test:coverage
open coverage/index.html
```
**CI Integration**:
- Codecov: Upload coverage to codecov.io
- Coveralls: Alternative coverage tracking
---
### 10.2 Test Dashboards
**Allure Report** (Optional):
```bash
npm install --save-dev @playwright/test allure-playwright
```
**Configuration**:
```javascript
// playwright.config.js
reporter: [
['allure-playwright'],
],
```
---
## 11. Recommended VS Code Extensions
- **Jest**: orta.vscode-jest
- **Playwright Test for VSCode**: ms-playwright.playwright
- **ESLint**: dbaeumer.vscode-eslint
- **Prettier**: esbenp.prettier-vscode
- **Code Coverage**: ryanluker.vscode-coverage-gutters
---
## 12. Quick Start Commands
**Setup**:
```bash
npm install
npm run test:setup # Install browsers, etc.
```
**Development**:
```bash
npm run test:watch # Unit tests in watch mode
npm run test:e2e:headed # E2E tests with browser visible
```
**CI/CD**:
```bash
npm run lint
npm run test:coverage
npm run test:e2e
npm run test:perf
npm run test:a11y
```
**Debugging**:
```bash
npm run test:debug # Debug Jest tests
npm run test:e2e:debug # Debug Playwright tests
```
---
## Support and Resources
- **Jest Documentation**: https://jestjs.io/
- **Playwright Documentation**: https://playwright.dev/
- **Testing Library**: https://testing-library.com/
- **axe-core**: https://github.com/dequelabs/axe-core
- **Percy**: https://percy.io/
- **Lighthouse**: https://developers.google.com/web/tools/lighthouse