# 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
