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

12 KiB

Test Scenarios (JSON Format)

This directory contains structured test scenarios in JSON format for automated testing of specific chess game behaviors.

Scenario Format

{
  "id": "unique-scenario-id",
  "name": "Scenario Name",
  "description": "Detailed description",
  "category": "category-name",
  "priority": "high|medium|low",
  "setup": {
    "fen": "FEN string",
    "description": "Setup description"
  },
  "steps": [
    {
      "action": "action-type",
      "params": {},
      "expected": {}
    }
  ],
  "assertions": [
    {
      "type": "assertion-type",
      "expected": "expected-value"
    }
  ]
}

Available Scenarios

Basic Movement Scenarios

Pawn Movement

File: pawn-movement.json

{
  "id": "pawn-001",
  "name": "Pawn Initial Two-Square Move",
  "description": "Verify pawn can move two squares from starting position",
  "category": "piece-movement",
  "priority": "high",
  "setup": {
    "fen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
    "description": "Initial board position"
  },
  "steps": [
    {
      "action": "selectPiece",
      "params": { "square": "e2" },
      "expected": { "validMoves": ["e3", "e4"] }
    },
    {
      "action": "movePiece",
      "params": { "from": "e2", "to": "e4" },
      "expected": { "success": true }
    }
  ],
  "assertions": [
    { "type": "pieceAt", "square": "e4", "expected": "white-pawn" },
    { "type": "pieceAt", "square": "e2", "expected": null },
    { "type": "turn", "expected": "black" }
  ]
}

Knight Jump

File: knight-jump.json

{
  "id": "knight-001",
  "name": "Knight Jumps Over Pieces",
  "description": "Verify knight can jump over blocking pieces",
  "category": "piece-movement",
  "priority": "high",
  "setup": {
    "fen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
    "description": "Initial position with pawns blocking"
  },
  "steps": [
    {
      "action": "movePiece",
      "params": { "from": "b1", "to": "c3" },
      "expected": { "success": true }
    }
  ],
  "assertions": [
    { "type": "pieceAt", "square": "c3", "expected": "white-knight" },
    { "type": "pieceAt", "square": "b1", "expected": null }
  ]
}

Special Moves Scenarios

En Passant

File: en-passant.json

{
  "id": "special-001",
  "name": "En Passant Capture",
  "description": "Verify en passant capture works correctly",
  "category": "special-moves",
  "priority": "high",
  "setup": {
    "fen": "rnbqkbnr/ppp1pppp/8/3pP3/8/8/PPPP1PPP/RNBQKBNR w KQkq d6 0 2",
    "description": "White pawn on e5, black just moved d7-d5"
  },
  "steps": [
    {
      "action": "movePiece",
      "params": { "from": "e5", "to": "d6" },
      "expected": { "success": true, "captureType": "en-passant" }
    }
  ],
  "assertions": [
    { "type": "pieceAt", "square": "d6", "expected": "white-pawn" },
    { "type": "pieceAt", "square": "d5", "expected": null },
    { "type": "pieceAt", "square": "e5", "expected": null },
    { "type": "capturedPieces", "color": "black", "expected": ["pawn"] }
  ]
}

Castling Kingside

File: castling-kingside.json

{
  "id": "castling-001",
  "name": "Kingside Castling",
  "description": "Verify kingside castling moves both king and rook",
  "category": "special-moves",
  "priority": "high",
  "setup": {
    "fen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQK2R w KQkq - 0 1",
    "description": "Cleared path for kingside castling"
  },
  "steps": [
    {
      "action": "movePiece",
      "params": { "from": "e1", "to": "g1" },
      "expected": { "success": true, "moveType": "castling" }
    }
  ],
  "assertions": [
    { "type": "pieceAt", "square": "g1", "expected": "white-king" },
    { "type": "pieceAt", "square": "f1", "expected": "white-rook" },
    { "type": "pieceAt", "square": "e1", "expected": null },
    { "type": "pieceAt", "square": "h1", "expected": null },
    { "type": "castlingRights", "white": { "kingside": false, "queenside": true } }
  ]
}

Pawn Promotion

File: pawn-promotion.json

{
  "id": "promotion-001",
  "name": "Pawn Promotion to Queen",
  "description": "Verify pawn promotes to queen on 8th rank",
  "category": "special-moves",
  "priority": "high",
  "setup": {
    "fen": "4k3/P7/8/8/8/8/8/4K3 w - - 0 1",
    "description": "White pawn on a7 ready to promote"
  },
  "steps": [
    {
      "action": "movePiece",
      "params": { "from": "a7", "to": "a8", "promotion": "queen" },
      "expected": { "success": true, "moveType": "promotion" }
    }
  ],
  "assertions": [
    { "type": "pieceAt", "square": "a8", "expected": "white-queen" },
    { "type": "pieceAt", "square": "a7", "expected": null }
  ]
}

Game State Scenarios

Check Detection

File: check-detection.json

{
  "id": "gamestate-001",
  "name": "Check Detection",
  "description": "Verify check is detected and displayed",
  "category": "game-state",
  "priority": "critical",
  "setup": {
    "fen": "rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2",
    "description": "Standard position"
  },
  "steps": [
    {
      "action": "movePiece",
      "params": { "from": "f1", "to": "c4" },
      "expected": { "success": true }
    },
    {
      "action": "movePiece",
      "params": { "from": "d8", "to": "h4" },
      "expected": { "success": true, "check": true }
    }
  ],
  "assertions": [
    { "type": "inCheck", "color": "white", "expected": true },
    { "type": "checkIndicator", "visible": true },
    { "type": "validMoves", "mustEscapeCheck": true }
  ]
}

Checkmate

File: checkmate-fools-mate.json

{
  "id": "checkmate-001",
  "name": "Fool's Mate Checkmate",
  "description": "Verify checkmate detection in Fool's Mate",
  "category": "game-state",
  "priority": "critical",
  "setup": {
    "fen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
    "description": "Initial position"
  },
  "steps": [
    { "action": "movePiece", "params": { "from": "f2", "to": "f3" } },
    { "action": "movePiece", "params": { "from": "e7", "to": "e5" } },
    { "action": "movePiece", "params": { "from": "g2", "to": "g4" } },
    {
      "action": "movePiece",
      "params": { "from": "d8", "to": "h4" },
      "expected": { "success": true, "checkmate": true }
    }
  ],
  "assertions": [
    { "type": "gameOver", "expected": true },
    { "type": "result", "expected": "black-wins" },
    { "type": "reason", "expected": "checkmate" },
    { "type": "inCheckmate", "color": "white", "expected": true }
  ]
}

Stalemate

File: stalemate.json

{
  "id": "gamestate-003",
  "name": "Stalemate Detection",
  "description": "Verify stalemate results in draw",
  "category": "game-state",
  "priority": "high",
  "setup": {
    "fen": "k7/8/1Q6/8/8/8/8/7K b - - 0 1",
    "description": "Black king with no legal moves, not in check"
  },
  "steps": [],
  "assertions": [
    { "type": "gameOver", "expected": true },
    { "type": "result", "expected": "draw" },
    { "type": "reason", "expected": "stalemate" },
    { "type": "legalMoves", "color": "black", "expected": [] }
  ]
}

UI Interaction Scenarios

Drag and Drop

File: drag-drop-move.json

{
  "id": "ui-001",
  "name": "Drag and Drop Valid Move",
  "description": "Verify drag-drop interaction for valid move",
  "category": "ui-interaction",
  "priority": "high",
  "setup": {
    "fen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
    "description": "Initial position"
  },
  "steps": [
    {
      "action": "dragStart",
      "params": { "square": "e2" },
      "expected": { "dragActive": true, "pieceSelected": true }
    },
    {
      "action": "dragOver",
      "params": { "square": "e4" },
      "expected": { "validMoveHighlight": true }
    },
    {
      "action": "drop",
      "params": { "square": "e4" },
      "expected": { "success": true, "pieceAt": "e4" }
    }
  ],
  "assertions": [
    { "type": "pieceAt", "square": "e4", "expected": "white-pawn" },
    { "type": "dragActive", "expected": false }
  ]
}

Click to Move

File: click-to-move.json

{
  "id": "ui-002",
  "name": "Click-Select-Click-Move",
  "description": "Verify click-based move selection",
  "category": "ui-interaction",
  "priority": "high",
  "setup": {
    "fen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
    "description": "Initial position"
  },
  "steps": [
    {
      "action": "click",
      "params": { "square": "e2" },
      "expected": { "pieceSelected": true, "validMovesHighlighted": ["e3", "e4"] }
    },
    {
      "action": "click",
      "params": { "square": "e4" },
      "expected": { "success": true }
    }
  ],
  "assertions": [
    { "type": "pieceAt", "square": "e4", "expected": "white-pawn" },
    { "type": "selectedSquare", "expected": null }
  ]
}

Error Handling Scenarios

Invalid Move

File: invalid-move.json

{
  "id": "error-001",
  "name": "Invalid Move Rejection",
  "description": "Verify invalid moves are rejected with feedback",
  "category": "error-handling",
  "priority": "high",
  "setup": {
    "fen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
    "description": "Initial position"
  },
  "steps": [
    {
      "action": "movePiece",
      "params": { "from": "e2", "to": "e5" },
      "expected": { "success": false, "error": "Invalid move" }
    }
  ],
  "assertions": [
    { "type": "pieceAt", "square": "e2", "expected": "white-pawn" },
    { "type": "pieceAt", "square": "e5", "expected": null },
    { "type": "errorMessage", "visible": true }
  ]
}

Move Opponent's Piece

File: wrong-color-move.json

{
  "id": "error-002",
  "name": "Cannot Move Opponent's Piece",
  "description": "Verify player cannot move opponent's pieces",
  "category": "error-handling",
  "priority": "critical",
  "setup": {
    "fen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
    "description": "White to move"
  },
  "steps": [
    {
      "action": "movePiece",
      "params": { "from": "e7", "to": "e5" },
      "expected": { "success": false, "error": "Wrong turn" }
    }
  ],
  "assertions": [
    { "type": "pieceAt", "square": "e7", "expected": "black-pawn" },
    { "type": "turn", "expected": "white" }
  ]
}

Usage in Tests

import scenario from './test-data/scenarios/pawn-movement.json';

describe(scenario.name, () => {
  test(scenario.description, async () => {
    // Setup
    const chess = new Chess(scenario.setup.fen);

    // Execute steps
    for (const step of scenario.steps) {
      const result = executeAction(step.action, step.params);
      expect(result).toMatchObject(step.expected);
    }

    // Verify assertions
    for (const assertion of scenario.assertions) {
      verifyAssertion(chess, assertion);
    }
  });
});

Scenario Categories

  • piece-movement: Basic piece movements
  • special-moves: Castling, en passant, promotion
  • game-state: Check, checkmate, stalemate
  • ui-interaction: Drag-drop, click-to-move
  • error-handling: Invalid moves, wrong turn
  • performance: Load testing, stress testing

Adding New Scenarios

  1. Create JSON file with proper structure
  2. Validate JSON syntax
  3. Test scenario manually
  4. Add to appropriate category
  5. Update this README

Validation

const validateScenario = (scenario) => {
  return (
    scenario.id &&
    scenario.name &&
    scenario.category &&
    scenario.priority &&
    scenario.setup &&
    scenario.steps &&
    Array.isArray(scenario.assertions)
  );
};