# 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: [ '/tests/**/*.test.{js,jsx,ts,tsx}', '/src/**/__tests__/**/*.{js,jsx,ts,tsx}', ], // Module paths modulePaths: ['/src'], // Setup files setupFilesAfterEnv: ['/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)$': '/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