UNPKG

draughtsboard

Version:

draughtsboard, checkersboard implementation in javascript

555 lines (427 loc) 20.7 kB
describe('Performance and Memory 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('Initialization Performance', function() { it('should initialize quickly with default settings', function() { const startTime = performance.now(); const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { position: 'start' }); const endTime = performance.now(); const duration = endTime - startTime; expect(board).to.be.an('object'); expect(duration).to.be.lessThan(100); // Should initialize within 100ms $container.data('board', board); }); it('should initialize multiple boards efficiently', function() { const startTime = performance.now(); const boards = []; for (let i = 0; i < 5; i++) { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { position: i % 2 === 0 ? 'start' : { '1': 'w', '31': 'b' } }); expect(board).to.be.an('object'); boards.push(board); $container.data('board', board); } const endTime = performance.now(); const duration = endTime - startTime; expect(boards.length).to.equal(5); expect(duration).to.be.lessThan(500); // 5 boards in under 500ms }); it('should handle large initial positions efficiently', function() { const startTime = performance.now(); // Create a position with many pieces const largePosition = {}; for (let i = 1; i <= 50; i++) { if (i % 3 !== 0) { // Skip every third square largePosition[i.toString()] = i % 2 === 0 ? 'w' : 'b'; } } const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { position: largePosition }); const endTime = performance.now(); const duration = endTime - startTime; expect(board).to.be.an('object'); expect(duration).to.be.lessThan(150); // Should handle large positions quickly $container.data('board', board); }); }); describe('Animation Performance', function() { it('should handle rapid position changes smoothly', function(done) { const $container = $('<div class="test-board">').appendTo('#test-boards'); let changeCount = 0; const startTime = performance.now(); const board = DraughtsBoard($container[0], { position: 'start', moveSpeed: 'fast', onChange: function() { changeCount++; if (changeCount === 20) { const endTime = performance.now(); const duration = endTime - startTime; expect(duration).to.be.lessThan(2000); // 20 changes in under 2 seconds done(); } } }); expect(board).to.be.an('object'); // Rapid position changes for (let i = 0; i < 20; i++) { setTimeout(() => { board.position({ [(i + 1).toString()]: 'w', [(31 + i % 20).toString()]: 'b' }); }, i * 50); } $container.data('board', board); setTimeout(() => { if (changeCount < 20) { done(); } }, 5000); }); it('should maintain smooth animations under load', function(done) { const $container = $('<div class="test-board">').appendTo('#test-boards'); let animationFrameCount = 0; const startTime = performance.now(); const board = DraughtsBoard($container[0], { position: 'start', moveSpeed: 100, // Slower to test smoothness onMoveEnd: function() { animationFrameCount++; if (animationFrameCount === 5) { const endTime = performance.now(); const duration = endTime - startTime; // Should complete without blocking the UI expect(duration).to.be.lessThan(3000); done(); } } }); expect(board).to.be.an('object'); // Multiple overlapping animations board.move('1-5'); board.move('2-6'); board.move('3-7'); board.move('31-27'); board.move('32-28'); $container.data('board', board); setTimeout(() => { if (animationFrameCount === 0) { done(); } }, 5000); }); it('should optimize DOM updates during animations', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { position: 'start', moveSpeed: 0 // Instant for testing }); expect(board).to.be.an('object'); const startTime = performance.now(); // Many rapid moves for (let i = 0; i < 10; i++) { board.move(`${i + 1}-${i + 11}`); } const endTime = performance.now(); const duration = endTime - startTime; expect(duration).to.be.lessThan(50); // Instant moves should be very fast expect(board.position()).to.be.an('object'); $container.data('board', board); }); }); describe('Memory Management', function() { it('should properly clean up on destroy', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { draggable: true, position: 'start', onDragStart: function() {}, onDrop: function() {}, onChange: function() {}, onMouseoverSquare: function() {}, onMouseoutSquare: function() {} }); expect(board).to.be.an('object'); // Verify board created DOM elements const initialChildCount = $container.children().length; expect(initialChildCount).to.be.greaterThan(0); // Destroy board board.destroy(); // Verify cleanup expect($container.children().length).to.equal(0); expect($container.html()).to.equal(''); }); it('should handle multiple create/destroy cycles', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); for (let i = 0; i < 10; i++) { const board = DraughtsBoard($container[0], { position: 'start' }); expect(board).to.be.an('object'); expect($container.find('.board-b72b1')).to.have.length(1); board.destroy(); expect($container.html()).to.equal(''); } }); it('should not leak event listeners', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); let eventCount = 0; // Create and destroy multiple boards with events for (let i = 0; i < 5; i++) { const board = DraughtsBoard($container[0], { draggable: true, position: 'start', onDragStart: function() { eventCount++; }, onDrop: function() { return 'snapback'; }, onChange: function() { eventCount++; } }); expect(board).to.be.an('object'); // Trigger some events board.move('1-5'); board.destroy(); } // After all boards are destroyed, no events should fire const initialEventCount = eventCount; // Try to trigger events on the container $container.trigger('mousedown'); $container.trigger('click'); expect(eventCount).to.equal(initialEventCount); // No new events }); it('should handle large position objects efficiently', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); // Create very large position object const hugePosition = {}; for (let i = 1; i <= 50; i++) { hugePosition[i.toString()] = i % 4 === 0 ? 'W' : i % 4 === 1 ? 'w' : i % 4 === 2 ? 'B' : 'b'; } const startTime = performance.now(); const board = DraughtsBoard($container[0], { position: hugePosition }); const endTime = performance.now(); const duration = endTime - startTime; expect(board).to.be.an('object'); expect(duration).to.be.lessThan(200); // Should handle efficiently // Test position manipulation const position = board.position(); expect(Object.keys(position).length).to.equal(50); $container.data('board', board); }); }); describe('DOM Performance', function() { it('should minimize DOM queries during operations', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { position: 'start' }); expect(board).to.be.an('object'); const startTime = performance.now(); // Operations that might trigger DOM queries board.flip(); board.orientation('black'); board.orientation('white'); board.resize(); board.clear(); board.start(); const endTime = performance.now(); const duration = endTime - startTime; expect(duration).to.be.lessThan(100); // Should be fast expect(board.position()).to.be.an('object'); $container.data('board', board); }); it('should efficiently update only changed pieces', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { position: 'start' }); expect(board).to.be.an('object'); const startTime = performance.now(); // Make single piece changes board.position({ '1': 'w', '5': 'w', '31': 'b', '35': 'b' }); board.position({ '2': 'w', '6': 'w', '32': 'b', '36': 'b' }); board.position({ '3': 'w', '7': 'w', '33': 'b', '37': 'b' }); const endTime = performance.now(); const duration = endTime - startTime; expect(duration).to.be.lessThan(50); // Incremental updates should be fast $container.data('board', board); }); it('should handle window resize efficiently', function(done) { 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'); let resizeCount = 0; const startTime = performance.now(); // Simulate multiple rapid resizes const resizeInterval = setInterval(() => { const newSize = 300 + (resizeCount * 20); $container.css({ width: `${newSize}px`, height: `${newSize}px` }); board.resize(); resizeCount++; if (resizeCount >= 10) { clearInterval(resizeInterval); const endTime = performance.now(); const duration = endTime - startTime; expect(duration).to.be.lessThan(500); // 10 resizes in under 500ms expect(board.position()).to.be.an('object'); done(); } }, 20); $container.data('board', board); }); }); describe('Concurrent Operations', function() { it('should handle concurrent position updates', function(done) { const $container = $('<div class="test-board">').appendTo('#test-boards'); let operationCount = 0; const board = DraughtsBoard($container[0], { position: 'start', onChange: function() { operationCount++; if (operationCount >= 20) { // All operations should complete successfully expect(board.position()).to.be.an('object'); done(); } } }); expect(board).to.be.an('object'); // Concurrent operations for (let i = 0; i < 20; i++) { setTimeout(() => { const position = {}; position[(i % 50 + 1).toString()] = i % 2 === 0 ? 'w' : 'b'; board.position(position); }, Math.random() * 100); } $container.data('board', board); setTimeout(() => { if (operationCount < 20) { done(); } }, 2000); }); it('should maintain stability under stress', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { position: 'start' }); expect(board).to.be.an('object'); const startTime = performance.now(); // Stress test with many operations for (let i = 0; i < 100; i++) { if (i % 10 === 0) board.clear(); else if (i % 7 === 0) board.start(); else if (i % 5 === 0) board.flip(); else if (i % 3 === 0) board.resize(); else board.move(`${(i % 50) + 1}-${((i + 1) % 50) + 1}`); } const endTime = performance.now(); const duration = endTime - startTime; expect(duration).to.be.lessThan(1000); // Should complete within 1 second expect(board.position()).to.be.an('object'); // Should still be functional $container.data('board', board); }); }); describe('Browser Compatibility Performance', function() { it('should perform consistently across different jQuery versions', function() { // This test assumes jQuery is loaded expect($).to.be.a('function'); expect($.fn.jquery).to.be.a('string'); const $container = $('<div class="test-board">').appendTo('#test-boards'); const startTime = performance.now(); const board = DraughtsBoard($container[0], { position: 'start', draggable: true }); const endTime = performance.now(); const duration = endTime - startTime; expect(board).to.be.an('object'); expect(duration).to.be.lessThan(200); // Should work efficiently with current jQuery $container.data('board', board); }); it('should handle CSS animations efficiently', function(done) { const $container = $('<div class="test-board">').appendTo('#test-boards'); let animationCount = 0; const board = DraughtsBoard($container[0], { position: 'start', moveSpeed: 'fast', onMoveEnd: function() { animationCount++; if (animationCount === 5) { // Animations should complete without performance issues expect(board.position()).to.be.an('object'); done(); } } }); expect(board).to.be.an('object'); // Trigger multiple animations board.move('1-5'); board.move('2-6'); board.move('3-7'); board.move('31-27'); board.move('32-28'); $container.data('board', board); setTimeout(() => { if (animationCount === 0) { done(); } }, 2000); }); }); describe('Resource Cleanup', function() { it('should clean up timers and intervals', function(done) { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { position: 'start', moveSpeed: 200 // Slow enough to have active timers }); expect(board).to.be.an('object'); // Start an animation board.move('1-5'); // Destroy immediately (should clean up any timers) setTimeout(() => { board.destroy(); // Board should be cleaned up expect($container.html()).to.equal(''); done(); }, 50); }); it('should handle cleanup during active animations', function() { const $container = $('<div class="test-board">').appendTo('#test-boards'); const board = DraughtsBoard($container[0], { position: 'start', moveSpeed: 1000 // Very slow animation }); expect(board).to.be.an('object'); // Start multiple slow animations board.move('1-5'); board.move('2-6'); board.move('3-7'); // Destroy during animations board.destroy(); // Should be cleaned up despite active animations expect($container.html()).to.equal(''); }); }); });