UNPKG

draughtsboard

Version:

draughtsboard, checkersboard implementation in javascript

692 lines (524 loc) 25.3 kB
describe('Board Method Tests', function() { beforeEach(function() { $('#test-boards').empty(); }); afterEach(function() { $('#test-boards .test-board').each(function() { const $board = $(this); if($board.data('board') && $board.data('board').destroy) { $board.data('board').destroy(); } }); $('#test-boards').empty(); }); describe('Core Board Methods', function() { it('should have all required methods', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0]); expect(board).to.be.an('object'); // Check for all core methods expect(board.clear).to.be.a('function'); expect(board.destroy).to.be.a('function'); expect(board.fen).to.be.a('function'); expect(board.flip).to.be.a('function'); expect(board.move).to.be.a('function'); expect(board.orientation).to.be.a('function'); expect(board.position).to.be.a('function'); expect(board.resize).to.be.a('function'); expect(board.start).to.be.a('function'); $container.data('board', board); }); }); describe('clear() method', function() { it('should clear the board without animation', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { position: 'start' }); expect(board).to.be.an('object'); // Verify board has pieces initially let initialPosition = board.position(); expect(Object.keys(initialPosition).length).to.be.greaterThan(0); // Clear the board board.clear(); // Verify board is empty const clearedPosition = board.position(); expect(Object.keys(clearedPosition).length).to.equal(0); $container.data('board', board); }); it('should clear the board with animation', function(done) { const $container = $('<div class="test-board">').appendTo('#test-boards'); let animationComplete = false; const board = DraughtsBoard($container[0], { position: 'start', trashSpeed: 'fast', onMoveEnd: function() { animationComplete = true; // Verify board is cleared const position = board.position(); expect(Object.keys(position).length).to.equal(0); done(); } }); expect(board).to.be.an('object'); // Clear with animation board.clear(true); $container.data('board', board); // Fallback setTimeout(() => { if (!animationComplete) { done(); } }, 1000); }); it('should trigger onChange when clearing', function() { let changeCount = 0; let oldPos, newPos; const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { position: 'start', onChange: function(oldPosition, newPosition) { changeCount++; oldPos = oldPosition; newPos = newPosition; } }); expect(board).to.be.an('object'); board.clear(); expect(changeCount).to.be.greaterThan(0); expect(oldPos).to.be.an('object'); expect(newPos).to.be.an('object'); expect(Object.keys(newPos).length).to.equal(0); $container.data('board', board); }); }); describe('destroy() method', function() { it('should completely destroy the board', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { position: 'start' }); expect(board).to.be.an('object'); // Verify board elements exist expect($container.find('.board-b72b1')).to.have.length(1); // Destroy the board board.destroy(); // Verify board elements are removed expect($container.find('.board-b72b1')).to.have.length(0); expect($container.html()).to.equal(''); }); it('should handle multiple destroy calls gracefully', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0]); expect(board).to.be.an('object'); // Multiple destroy calls should not throw errors expect(function() { board.destroy(); board.destroy(); board.destroy(); }).to.not.throw(); expect($container.html()).to.equal(''); }); it('should clean up event listeners', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { draggable: true, position: 'start', onDragStart: function() {}, onDrop: function() {}, onMouseoverSquare: function() {}, onMouseoutSquare: function() {} }); expect(board).to.be.an('object'); // Destroy should clean up all event listeners board.destroy(); // Container should be empty expect($container.html()).to.equal(''); }); }); describe('fen() method', function() { it('should return current position as FEN string', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { position: 'start' }); expect(board).to.be.an('object'); const fen = board.fen(); expect(fen).to.be.a('string'); expect(fen).to.match(/^[WB]:/); // Should start with turn indicator $container.data('board', board); }); it('should return consistent FEN for empty board', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0]); expect(board).to.be.an('object'); const fen = board.fen(); expect(fen).to.be.a('string'); expect(fen).to.equal('W::'); // Empty board FEN $container.data('board', board); }); it('should return FEN that can be used to recreate position', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const originalPosition = { '1': 'w', '2': 'W', '31': 'b', '32': 'B' }; const board = DraughtsBoard($container[0], { position: originalPosition }); expect(board).to.be.an('object'); const fen = board.fen(); // Create new board with the FEN const $container2 = $('<div class="test-board">').appendTo('#test-boards'); const board2 = DraughtsBoard($container2[0], { position: fen }); const newPosition = board2.position(); expect(newPosition['1']).to.equal('w'); expect(newPosition['2']).to.equal('W'); expect(newPosition['31']).to.equal('b'); expect(newPosition['32']).to.equal('B'); $container.data('board', board); $container2.data('board', board2); }); }); describe('flip() method', function() { it('should flip board orientation', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { orientation: 'white' }); expect(board).to.be.an('object'); expect(board.orientation()).to.equal('white'); board.flip(); expect(board.orientation()).to.equal('black'); board.flip(); expect(board.orientation()).to.equal('white'); $container.data('board', board); }); it('should maintain position after flip', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const position = { '1': 'w', '31': 'b' }; const board = DraughtsBoard($container[0], { position: position }); expect(board).to.be.an('object'); const beforeFlip = board.position(); board.flip(); const afterFlip = board.position(); // Position should remain the same expect(afterFlip['1']).to.equal(beforeFlip['1']); expect(afterFlip['31']).to.equal(beforeFlip['31']); $container.data('board', board); }); it('should update visual representation after flip', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { position: 'start' }); expect(board).to.be.an('object'); // Verify board exists expect($container.find('.board-b72b1')).to.have.length(1); board.flip(); // Board should still exist and be functional expect($container.find('.board-b72b1')).to.have.length(1); expect(board.orientation()).to.equal('black'); $container.data('board', board); }); }); describe('move() method', function() { it('should execute simple moves', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { position: { '1': 'w' } }); expect(board).to.be.an('object'); // Execute move board.move('1-5'); const position = board.position(); expect(position['5']).to.equal('w'); expect(position['1']).to.be.undefined; $container.data('board', board); }); it('should handle capture moves', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { position: { '1': 'w', '31': 'b' } }); expect(board).to.be.an('object'); // Execute capture move board.move('1x31'); const position = board.position(); expect(position['31']).to.equal('w'); expect(position['1']).to.be.undefined; $container.data('board', board); }); it('should trigger move animations', function(done) { const $container = $('<div class="test-board">').appendTo('#test-boards'); let moveComplete = false; const board = DraughtsBoard($container[0], { position: { '1': 'w' }, moveSpeed: 'fast', onMoveEnd: function(source, target, piece) { moveComplete = true; expect(source).to.equal('1'); expect(target).to.equal('5'); expect(piece).to.equal('w'); done(); } }); expect(board).to.be.an('object'); board.move('1-5'); $container.data('board', board); setTimeout(() => { if (!moveComplete) { done(); } }, 1000); }); it('should handle invalid move notation gracefully', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { position: { '1': 'w' } }); expect(board).to.be.an('object'); const originalPosition = board.position(); // Try invalid moves expect(function() { board.move('invalid'); board.move('1-'); board.move('1-99'); board.move(''); }).to.not.throw(); // Position should remain unchanged const newPosition = board.position(); expect(newPosition['1']).to.equal(originalPosition['1']); $container.data('board', board); }); it('should handle multiple sequential moves', function(done) { const $container = $('<div class="test-board">').appendTo('#test-boards'); let moveCount = 0; const board = DraughtsBoard($container[0], { position: { '1': 'w', '2': 'b' }, moveSpeed: 'fast', onMoveEnd: function() { moveCount++; if (moveCount === 2) { const position = board.position(); expect(position['5']).to.equal('w'); expect(position['6']).to.equal('b'); done(); } } }); expect(board).to.be.an('object'); board.move('1-5'); board.move('2-6'); $container.data('board', board); setTimeout(() => { if (moveCount === 0) { done(); } }, 2000); }); }); describe('orientation() method', function() { it('should get current orientation', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { orientation: 'black' }); expect(board).to.be.an('object'); expect(board.orientation()).to.equal('black'); $container.data('board', board); }); it('should set new orientation', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { orientation: 'white' }); expect(board).to.be.an('object'); expect(board.orientation()).to.equal('white'); board.orientation('black'); expect(board.orientation()).to.equal('black'); $container.data('board', board); }); it('should handle invalid orientation values gracefully', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0]); expect(board).to.be.an('object'); const originalOrientation = board.orientation(); // Try invalid orientations board.orientation('invalid'); board.orientation(''); board.orientation(123); board.orientation(null); // Should fallback to valid orientation const currentOrientation = board.orientation(); expect(['white', 'black']).to.include(currentOrientation); $container.data('board', board); }); }); describe('resize() method', function() { it('should handle board resize', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); $container.css({ width: '400px', height: '400px' }); const board = DraughtsBoard($container[0], { position: 'start' }); expect(board).to.be.an('object'); // Change container size $container.css({ width: '600px', height: '600px' }); // Resize board board.resize(); // Board should still function expect(board.position()).to.be.an('object'); expect($container.find('.board-b72b1')).to.have.length(1); $container.data('board', board); }); it('should maintain position after resize', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const position = { '1': 'w', '31': 'b' }; const board = DraughtsBoard($container[0], { position: position }); expect(board).to.be.an('object'); const beforeResize = board.position(); // Resize $container.css({ width: '500px', height: '500px' }); board.resize(); const afterResize = board.position(); // Position should be preserved expect(afterResize['1']).to.equal(beforeResize['1']); expect(afterResize['31']).to.equal(beforeResize['31']); $container.data('board', board); }); it('should handle resize with zero dimensions', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0]); expect(board).to.be.an('object'); // Set zero dimensions $container.css({ width: '0px', height: '0px' }); expect(function() { board.resize(); }).to.not.throw(); $container.data('board', board); }); }); describe('start() method', function() { it('should set position to start', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0]); expect(board).to.be.an('object'); // Start position board.start(); const position = board.position(); expect(Object.keys(position).length).to.be.greaterThan(0); // Should have both white and black pieces const pieces = Object.values(position); expect(pieces.some(p => p === 'w' || p === 'W')).to.be.true; expect(pieces.some(p => p === 'b' || p === 'B')).to.be.true; $container.data('board', board); }); it('should animate to start position when useAnimation is true', function(done) { const $container = $('<div class="test-board">').appendTo('#test-boards'); let animationComplete = false; const board = DraughtsBoard($container[0], { position: { '25': 'w' }, // Non-start position moveSpeed: 'fast', onMoveEnd: function() { animationComplete = true; const position = board.position(); expect(Object.keys(position).length).to.be.greaterThan(1); done(); } }); expect(board).to.be.an('object'); board.start(true); $container.data('board', board); setTimeout(() => { if (!animationComplete) { done(); } }, 1000); }); it('should trigger onChange when starting', function() { let changeCount = 0; const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { onChange: function(oldPos, newPos) { changeCount++; expect(oldPos).to.be.an('object'); expect(newPos).to.be.an('object'); expect(Object.keys(newPos).length).to.be.greaterThan(Object.keys(oldPos).length); } }); expect(board).to.be.an('object'); board.start(); expect(changeCount).to.be.greaterThan(0); $container.data('board', board); }); }); describe('Method chaining and combinations', function() { it('should handle method combinations', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0]); expect(board).to.be.an('object'); // Chain multiple method calls board.start(); board.flip(); board.move('1-5'); board.clear(); board.start(); // Board should still be functional expect(board.position()).to.be.an('object'); expect(Object.keys(board.position()).length).to.be.greaterThan(0); $container.data('board', board); }); it('should maintain state consistency across method calls', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0]); expect(board).to.be.an('object'); // Complex sequence of operations board.start(); const startPos = board.position(); board.orientation('black'); expect(board.orientation()).to.equal('black'); board.clear(); expect(Object.keys(board.position()).length).to.equal(0); board.position(startPos); expect(Object.keys(board.position()).length).to.equal(Object.keys(startPos).length); $container.data('board', board); }); }); describe('Error handling and edge cases', function() { it('should handle method calls on destroyed board gracefully', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0]); expect(board).to.be.an('object'); board.destroy(); // Method calls on destroyed board should not throw expect(function() { board.clear(); board.flip(); board.move('1-5'); board.position('start'); board.resize(); board.start(); board.fen(); board.orientation('white'); }).to.not.throw(); }); it('should handle rapid method calls', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0]); expect(board).to.be.an('object'); // Rapid method calls should not break the board for(let i = 0; i < 10; i++) { board.clear(); board.start(); board.flip(); } // Board should still be functional expect(board.position()).to.be.an('object'); $container.data('board', board); }); }); });