Some checks failed
This commit fixes two bugs: 1. Issue #7: Missing status message DOM element - Added #status-message div to index.html - Added CSS styling with type-based classes (info, success, error) - Enhanced showMessage() to apply type classes for visual styling - Messages auto-hide after 3 seconds with fade-in animation 2. Column resizing visual bug: - Changed grid-template-columns from flexible (1fr 3fr 1fr) - To fixed minimum widths: minmax(200px, 250px) minmax(600px, 3fr) minmax(200px, 250px) - Prevents columns from resizing when content changes (captured pieces, move history) - Maintains stable layout throughout gameplay Tests: - Added status-message.test.js with 10 test cases - Added column-resize.test.js with 8 test cases - Tests verify DOM element existence, CSS styling, auto-hide behavior, and layout stability 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
213 lines
8.4 KiB
JavaScript
213 lines
8.4 KiB
JavaScript
/**
|
|
* Column Resize Bug Tests
|
|
* Tests to verify that columns maintain consistent width during gameplay
|
|
*/
|
|
|
|
import { test, expect } from '@playwright/test';
|
|
|
|
test.describe('Column Layout Stability', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.goto('http://localhost:8080');
|
|
await page.waitForLoadState('networkidle');
|
|
});
|
|
|
|
test('game container uses fixed minimum widths', async ({ page }) => {
|
|
const gameContainer = await page.locator('.game-container');
|
|
|
|
// Check computed styles
|
|
const styles = await gameContainer.evaluate((el) => {
|
|
const computed = window.getComputedStyle(el);
|
|
return {
|
|
display: computed.display,
|
|
gridTemplateColumns: computed.gridTemplateColumns
|
|
};
|
|
});
|
|
|
|
expect(styles.display).toBe('grid');
|
|
// Should use minmax() for fixed minimum widths
|
|
expect(styles.gridTemplateColumns).not.toBe('1fr 3fr 1fr');
|
|
});
|
|
|
|
test('left sidebar maintains minimum width', async ({ page }) => {
|
|
const leftSidebar = await page.locator('.captured-white');
|
|
|
|
const initialWidth = await leftSidebar.evaluate(el => el.offsetWidth);
|
|
expect(initialWidth).toBeGreaterThanOrEqual(200); // minmax(200px, 250px)
|
|
});
|
|
|
|
test('right sidebar maintains minimum width', async ({ page }) => {
|
|
const rightSidebar = await page.locator('.game-sidebar');
|
|
|
|
const initialWidth = await rightSidebar.evaluate(el => el.offsetWidth);
|
|
expect(initialWidth).toBeGreaterThanOrEqual(200); // minmax(200px, 250px)
|
|
});
|
|
|
|
test('board section maintains minimum width', async ({ page }) => {
|
|
const boardSection = await page.locator('.board-section');
|
|
|
|
const initialWidth = await boardSection.evaluate(el => el.offsetWidth);
|
|
expect(initialWidth).toBeGreaterThanOrEqual(600); // minmax(600px, 3fr)
|
|
});
|
|
|
|
test('columns do not resize when pieces are captured', async ({ page }) => {
|
|
// Get initial widths
|
|
const getWidths = async () => {
|
|
return await page.evaluate(() => {
|
|
const leftSidebar = document.querySelector('.captured-white');
|
|
const boardSection = document.querySelector('.board-section');
|
|
const rightSidebar = document.querySelector('.game-sidebar');
|
|
|
|
return {
|
|
left: leftSidebar.offsetWidth,
|
|
board: boardSection.offsetWidth,
|
|
right: rightSidebar.offsetWidth
|
|
};
|
|
});
|
|
};
|
|
|
|
const initialWidths = await getWidths();
|
|
|
|
// Make a move that captures a piece (simulate)
|
|
await page.evaluate(() => {
|
|
// Add captured piece to test resize behavior
|
|
const capturedList = document.querySelector('#captured-white-pieces');
|
|
if (capturedList) {
|
|
const piece = document.createElement('div');
|
|
piece.className = 'captured-piece white pawn';
|
|
piece.textContent = '♙';
|
|
capturedList.appendChild(piece);
|
|
}
|
|
});
|
|
|
|
await page.waitForTimeout(100); // Allow for any layout recalculation
|
|
|
|
const afterCaptureWidths = await getWidths();
|
|
|
|
// Columns should maintain their widths (within 1px for rounding)
|
|
expect(Math.abs(afterCaptureWidths.left - initialWidths.left)).toBeLessThanOrEqual(1);
|
|
expect(Math.abs(afterCaptureWidths.board - initialWidths.board)).toBeLessThanOrEqual(1);
|
|
expect(Math.abs(afterCaptureWidths.right - initialWidths.right)).toBeLessThanOrEqual(1);
|
|
});
|
|
|
|
test('columns do not resize when multiple pieces are captured', async ({ page }) => {
|
|
const getWidths = async () => {
|
|
return await page.evaluate(() => {
|
|
const leftSidebar = document.querySelector('.captured-white');
|
|
const boardSection = document.querySelector('.board-section');
|
|
const rightSidebar = document.querySelector('.game-sidebar');
|
|
|
|
return {
|
|
left: leftSidebar.offsetWidth,
|
|
board: boardSection.offsetWidth,
|
|
right: rightSidebar.offsetWidth
|
|
};
|
|
});
|
|
};
|
|
|
|
const initialWidths = await getWidths();
|
|
|
|
// Add multiple captured pieces
|
|
await page.evaluate(() => {
|
|
const capturedList = document.querySelector('#captured-white-pieces');
|
|
if (capturedList) {
|
|
const pieces = ['♙', '♘', '♗', '♖', '♕'];
|
|
pieces.forEach(symbol => {
|
|
const piece = document.createElement('div');
|
|
piece.className = 'captured-piece white';
|
|
piece.textContent = symbol;
|
|
capturedList.appendChild(piece);
|
|
});
|
|
}
|
|
});
|
|
|
|
await page.waitForTimeout(100);
|
|
|
|
const afterMultipleCapturesWidths = await getWidths();
|
|
|
|
// Columns should still maintain their widths
|
|
expect(Math.abs(afterMultipleCapturesWidths.left - initialWidths.left)).toBeLessThanOrEqual(1);
|
|
expect(Math.abs(afterMultipleCapturesWidths.board - initialWidths.board)).toBeLessThanOrEqual(1);
|
|
expect(Math.abs(afterMultipleCapturesWidths.right - initialWidths.right)).toBeLessThanOrEqual(1);
|
|
});
|
|
|
|
test('columns do not resize when move history grows', async ({ page }) => {
|
|
const getWidths = async () => {
|
|
return await page.evaluate(() => {
|
|
const leftSidebar = document.querySelector('.captured-white');
|
|
const boardSection = document.querySelector('.board-section');
|
|
const rightSidebar = document.querySelector('.game-sidebar');
|
|
|
|
return {
|
|
left: leftSidebar.offsetWidth,
|
|
board: boardSection.offsetWidth,
|
|
right: rightSidebar.offsetWidth
|
|
};
|
|
});
|
|
};
|
|
|
|
const initialWidths = await getWidths();
|
|
|
|
// Add move history entries
|
|
await page.evaluate(() => {
|
|
const moveHistory = document.querySelector('#move-history');
|
|
if (moveHistory) {
|
|
for (let i = 1; i <= 20; i++) {
|
|
const moveEntry = document.createElement('div');
|
|
moveEntry.className = 'move-entry';
|
|
moveEntry.innerHTML = `
|
|
<span class="move-number">${i}.</span>
|
|
<span class="move-notation white">e4</span>
|
|
<span class="move-notation black">e5</span>
|
|
`;
|
|
moveHistory.appendChild(moveEntry);
|
|
}
|
|
}
|
|
});
|
|
|
|
await page.waitForTimeout(100);
|
|
|
|
const afterMovesWidths = await getWidths();
|
|
|
|
// Columns should maintain their widths
|
|
expect(Math.abs(afterMovesWidths.left - initialWidths.left)).toBeLessThanOrEqual(1);
|
|
expect(Math.abs(afterMovesWidths.board - initialWidths.board)).toBeLessThanOrEqual(1);
|
|
expect(Math.abs(afterMovesWidths.right - initialWidths.right)).toBeLessThanOrEqual(1);
|
|
});
|
|
|
|
test('layout remains stable across window resize', async ({ page }) => {
|
|
// Set initial viewport
|
|
await page.setViewportSize({ width: 1400, height: 900 });
|
|
|
|
const getWidths = async () => {
|
|
return await page.evaluate(() => {
|
|
const leftSidebar = document.querySelector('.captured-white');
|
|
const boardSection = document.querySelector('.board-section');
|
|
const rightSidebar = document.querySelector('.game-sidebar');
|
|
|
|
return {
|
|
left: leftSidebar.offsetWidth,
|
|
board: boardSection.offsetWidth,
|
|
right: rightSidebar.offsetWidth
|
|
};
|
|
});
|
|
};
|
|
|
|
const widthsBefore = await getWidths();
|
|
|
|
// Resize window
|
|
await page.setViewportSize({ width: 1600, height: 900 });
|
|
await page.waitForTimeout(200);
|
|
|
|
const widthsAfter = await getWidths();
|
|
|
|
// Sidebar widths should remain close to their minimum (200px)
|
|
expect(widthsAfter.left).toBeGreaterThanOrEqual(200);
|
|
expect(widthsAfter.left).toBeLessThanOrEqual(250);
|
|
expect(widthsAfter.right).toBeGreaterThanOrEqual(200);
|
|
expect(widthsAfter.right).toBeLessThanOrEqual(250);
|
|
|
|
// Board should be able to grow
|
|
expect(widthsAfter.board).toBeGreaterThanOrEqual(600);
|
|
});
|
|
});
|