/** * @jest-environment jsdom */ import { King } from '../../../js/pieces/King.js'; import { Board } from '../../../js/game/Board.js'; describe('King', () => { let board; beforeEach(() => { board = new Board(); board.clear(); }); describe('One Square Movement', () => { test('king can move one square in any direction', () => { const king = new King('white', { row: 4, col: 4 }); board.setPiece(4, 4, king); const moves = king.getValidMoves(board); const expectedMoves = [ { row: 3, col: 3 }, { row: 3, col: 4 }, { row: 3, col: 5 }, { row: 4, col: 3 }, /* king here */ { row: 4, col: 5 }, { row: 5, col: 3 }, { row: 5, col: 4 }, { row: 5, col: 5 } ]; expect(moves).toHaveLength(8); expectedMoves.forEach(expected => { expect(moves).toContainEqual(expected); }); }); test('king in corner has 3 moves', () => { const king = new King('white', { row: 0, col: 0 }); board.setPiece(0, 0, king); const moves = king.getValidMoves(board); expect(moves).toHaveLength(3); expect(moves).toContainEqual({ row: 0, col: 1 }); expect(moves).toContainEqual({ row: 1, col: 0 }); expect(moves).toContainEqual({ row: 1, col: 1 }); }); test('king on edge has 5 moves', () => { const king = new King('white', { row: 0, col: 4 }); board.setPiece(0, 4, king); const moves = king.getValidMoves(board); expect(moves).toHaveLength(5); }); test('king cannot move two squares (except castling)', () => { const king = new King('white', { row: 4, col: 4 }); board.setPiece(4, 4, king); const moves = king.getValidMoves(board); // No move should be more than 1 square away moves.forEach(move => { const rowDiff = Math.abs(move.row - 4); const colDiff = Math.abs(move.col - 4); expect(rowDiff).toBeLessThanOrEqual(1); expect(colDiff).toBeLessThanOrEqual(1); }); }); }); describe('Cannot Move Into Check', () => { test('king cannot move into attacked square', () => { const whiteKing = new King('white', { row: 7, col: 4 }); const blackRook = { type: 'rook', color: 'black', position: { row: 0, col: 5 } }; board.setPiece(7, 4, whiteKing); board.setPiece(0, 5, blackRook); const moves = whiteKing.getValidMoves(board, board); // Cannot move to (7,5) or (6,5) - attacked by rook expect(moves).not.toContainEqual({ row: 7, col: 5 }); expect(moves).not.toContainEqual({ row: 6, col: 5 }); }); test('king cannot move adjacent to opponent king', () => { const whiteKing = new King('white', { row: 4, col: 4 }); const blackKing = { type: 'king', color: 'black', position: { row: 4, col: 6 } }; board.setPiece(4, 4, whiteKing); board.setPiece(4, 6, blackKing); const moves = whiteKing.getValidMoves(board, board); // Cannot move to (4,5) - adjacent to black king expect(moves).not.toContainEqual({ row: 4, col: 5 }); expect(moves).not.toContainEqual({ row: 3, col: 5 }); expect(moves).not.toContainEqual({ row: 5, col: 5 }); }); }); describe('Castling - Kingside', () => { test('king can castle kingside when conditions met', () => { const king = new King('white', { row: 7, col: 4 }); const rook = { type: 'rook', color: 'white', position: { row: 7, col: 7 }, hasMoved: false }; board.setPiece(7, 4, king); board.setPiece(7, 7, rook); const gameState = { castlingRights: { whiteKingside: true } }; const moves = king.getValidMoves(board, board, gameState); expect(moves).toContainEqual({ row: 7, col: 6, castling: 'kingside' }); }); test('cannot castle if king has moved', () => { const king = new King('white', { row: 7, col: 4 }); king.hasMoved = true; const rook = { type: 'rook', color: 'white', position: { row: 7, col: 7 }, hasMoved: false }; board.setPiece(7, 4, king); board.setPiece(7, 7, rook); const gameState = { castlingRights: { whiteKingside: false } }; const moves = king.getValidMoves(board, board, gameState); expect(moves).not.toContainEqual({ row: 7, col: 6, castling: 'kingside' }); }); test('cannot castle if rook has moved', () => { const king = new King('white', { row: 7, col: 4 }); const rook = { type: 'rook', color: 'white', position: { row: 7, col: 7 }, hasMoved: true }; board.setPiece(7, 4, king); board.setPiece(7, 7, rook); const gameState = { castlingRights: { whiteKingside: false } }; const moves = king.getValidMoves(board, board, gameState); expect(moves).not.toContainEqual({ row: 7, col: 6, castling: 'kingside' }); }); test('cannot castle through pieces', () => { const king = new King('white', { row: 7, col: 4 }); const rook = { type: 'rook', color: 'white', position: { row: 7, col: 7 }, hasMoved: false }; const bishop = { type: 'bishop', color: 'white', position: { row: 7, col: 5 } }; board.setPiece(7, 4, king); board.setPiece(7, 7, rook); board.setPiece(7, 5, bishop); const gameState = { castlingRights: { whiteKingside: true } }; const moves = king.getValidMoves(board, board, gameState); expect(moves).not.toContainEqual({ row: 7, col: 6, castling: 'kingside' }); }); test('cannot castle through check', () => { const king = new King('white', { row: 7, col: 4 }); const rook = { type: 'rook', color: 'white', position: { row: 7, col: 7 }, hasMoved: false }; const blackRook = { type: 'rook', color: 'black', position: { row: 0, col: 5 } }; board.setPiece(7, 4, king); board.setPiece(7, 7, rook); board.setPiece(0, 5, blackRook); const gameState = { castlingRights: { whiteKingside: true } }; const moves = king.getValidMoves(board, board, gameState); expect(moves).not.toContainEqual({ row: 7, col: 6, castling: 'kingside' }); }); test('cannot castle while in check', () => { const king = new King('white', { row: 7, col: 4 }); const rook = { type: 'rook', color: 'white', position: { row: 7, col: 7 }, hasMoved: false }; const blackRook = { type: 'rook', color: 'black', position: { row: 0, col: 4 } }; board.setPiece(7, 4, king); board.setPiece(7, 7, rook); board.setPiece(0, 4, blackRook); const gameState = { castlingRights: { whiteKingside: true }, inCheck: true }; const moves = king.getValidMoves(board, board, gameState); expect(moves).not.toContainEqual({ row: 7, col: 6, castling: 'kingside' }); }); }); describe('Castling - Queenside', () => { test('king can castle queenside when conditions met', () => { const king = new King('white', { row: 7, col: 4 }); const rook = { type: 'rook', color: 'white', position: { row: 7, col: 0 }, hasMoved: false }; board.setPiece(7, 4, king); board.setPiece(7, 0, rook); const gameState = { castlingRights: { whiteQueenside: true } }; const moves = king.getValidMoves(board, board, gameState); expect(moves).toContainEqual({ row: 7, col: 2, castling: 'queenside' }); }); }); });