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

14 KiB

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:

npm install --save-dev jest @types/jest

Configuration (jest.config.js):

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:

{
  "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:

npm install --save-dev @testing-library/dom
npm install --save-dev @testing-library/user-event

Setup (tests/setup.js):

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:

npm install --save-dev @playwright/test
npx playwright install

Configuration (playwright.config.js):

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):

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:

{
  "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

Purpose: Automated visual testing

Installation:

npm install --save-dev @percy/cli @percy/playwright

Configuration (.percy.yml):

version: 2
static:
  include: "public/**/*"
snapshot:
  widths:
    - 375
    - 768
    - 1280
  min-height: 1024
  percy-css: |
    .animated { animation: none !important; }

Usage in Tests:

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:

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:

npm install --save-dev @lhci/cli

Configuration (lighthouserc.js):

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:

{
  "scripts": {
    "test:perf": "lhci autorun",
    "test:perf:collect": "lhci collect",
    "test:perf:assert": "lhci assert"
  }
}

4.2 Custom Performance Tests

Using Performance API:

// 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:

npm install --save-dev @axe-core/playwright

Usage in Playwright:

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:

npm install --save-dev pa11y

Configuration (pa11y.config.js):

module.exports = {
  standard: 'WCAG2AA',
  runners: ['axe', 'htmlcs'],
  level: 'error',
  threshold: 0,
  chromeLaunchConfig: {
    args: ['--no-sandbox'],
  },
};

Script:

{
  "scripts": {
    "test:a11y": "pa11y http://localhost:3000 --config pa11y.config.js"
  }
}

6. Code Quality Tools

6.1 ESLint

Installation:

npm install --save-dev eslint eslint-config-airbnb-base

Configuration (.eslintrc.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:

npm install --save-dev prettier eslint-config-prettier

Configuration (.prettierrc):

{
  "singleQuote": true,
  "trailingComma": "all",
  "printWidth": 100,
  "tabWidth": 2,
  "semi": true
}

6.3 SonarQube (Optional)

For advanced code quality metrics:

npm install --save-dev sonarqube-scanner

7. Test Data Management

7.1 FEN Parser

Installation:

npm install --save-dev chess.js

Usage:

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:

// 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

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:

npm install --save-dev husky lint-staged
npx husky install

Configuration (.husky/pre-commit):

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx lint-staged

Lint-staged (package.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

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

// 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:

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):

npm install --save-dev @playwright/test allure-playwright

Configuration:

// playwright.config.js
reporter: [
  ['allure-playwright'],
],

  • 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:

npm install
npm run test:setup  # Install browsers, etc.

Development:

npm run test:watch  # Unit tests in watch mode
npm run test:e2e:headed  # E2E tests with browser visible

CI/CD:

npm run lint
npm run test:coverage
npm run test:e2e
npm run test:perf
npm run test:a11y

Debugging:

npm run test:debug  # Debug Jest tests
npm run test:e2e:debug  # Debug Playwright tests

Support and Resources