fix: resolve remaining test failures in CI
Pull Request / unit-tests (pull_request) Successful in 2m4s
Pull Request / analyze-bump-type (pull_request) Successful in 15s
Pull Request / build-and-deploy-ci (pull_request) Failing after 43m22s

- cucumber: use 'progress' formatter in CI (not progress-bar TTY)
- csv-upload: use timestamp in player names to avoid unique constraint
- elo-ratings: delete event_participants before players (FK constraint)
- epic3-rankings: use .first() on h1/h2 locator (strict mode)
- schedule-tab: look for button instead of anchor for Schedule tab
- team-config: wait for search input before filling (step 2 async)
- tournament-edit-allowTies: check for 'Edit Tournament' not 'Tournament Name'
- epic4-tournament-creation: submit button only on step 2, add waitForSelector
This commit is contained in:
2026-05-18 18:32:30 -07:00
parent feca7067b8
commit a0872d07ef
8 changed files with 59 additions and 30 deletions
+10 -7
View File
@@ -13,6 +13,7 @@ import path from 'path';
test.describe('CSV Upload Player Deduplication', () => {
let testTournamentId: number;
const testPlayerIds: number[] = [];
const ts = Date.now();
test.beforeAll(async () => {
// Create a test tournament
@@ -47,12 +48,14 @@ test.describe('CSV Upload Player Deduplication', () => {
});
}
// Delete test players (those with "Dedupe" in the name)
// Delete test players (those with "Dedupe" or "Aggregate Test" in the name)
await prisma.player.deleteMany({
where: {
name: {
contains: 'Dedupe',
},
OR: [
{ name: { contains: 'Dedupe' } },
{ name: { contains: 'Aggregate Test' } },
{ name: { contains: 'Whitespace' } },
],
},
});
@@ -163,8 +166,8 @@ test.describe('CSV Upload Player Deduplication', () => {
// First, create some players manually to simulate previous uploads
const player1 = await prisma.player.create({
data: {
name: 'Aggregate Test',
normalizedName: 'aggregate test',
name: `Aggregate Test ${ts}`,
normalizedName: `aggregate test ${ts}`,
currentElo: 1050,
gamesPlayed: 5,
wins: 3,
@@ -175,7 +178,7 @@ test.describe('CSV Upload Player Deduplication', () => {
// Upload a CSV with the same player name
const csvContent = `Event #,Round,Table,Seat 1,Seat 3,Odds Points,Seat 2,Seat 4,Evens Points
1,1,1,Aggregate Test,Test Player 1,5,Test Player 2,Test Player 3,3`;
1,1,1,Aggregate Test ${ts},Test Player 1,5,Test Player 2,Test Player 3,3`;
const csvPath = path.join(__dirname, 'temp-aggregate-test.csv');
fs.writeFileSync(csvPath, csvContent);
+1 -1
View File
@@ -17,7 +17,7 @@ module.exports = {
// Format options
format: [
'progress-bar',
process.env.CI ? 'progress' : 'progress-bar',
'pretty:cucumber-pretty'
],
+30 -12
View File
@@ -13,24 +13,33 @@ import path from 'path';
test.describe('Elo Rating Updates', () => {
test.beforeAll(async () => {
// Clean up any existing test data
const playerIds = await getEloTestPlayerIds();
// First delete matches that reference players
await prisma.match.deleteMany({
where: {
OR: [
{ player1P1Id: { in: await getEloTestPlayerIds() } },
{ player1P2Id: { in: await getEloTestPlayerIds() } },
{ player2P1Id: { in: await getEloTestPlayerIds() } },
{ player2P2Id: { in: await getEloTestPlayerIds() } },
{ player1P1Id: { in: playerIds } },
{ player1P2Id: { in: playerIds } },
{ player2P1Id: { in: playerIds } },
{ player2P2Id: { in: playerIds } },
]
}
});
// Then delete event participants that reference players
await prisma.eventParticipant.deleteMany({
where: {
playerId: { in: playerIds }
}
});
// Then delete partnerships
await prisma.partnershipStat.deleteMany({
where: {
OR: [
{ player1Id: { in: await getEloTestPlayerIds() } },
{ player2Id: { in: await getEloTestPlayerIds() } },
{ player1Id: { in: playerIds } },
{ player2Id: { in: playerIds } },
]
}
});
@@ -47,24 +56,33 @@ test.describe('Elo Rating Updates', () => {
test.afterAll(async () => {
// Clean up test data
const playerIds = await getEloTestPlayerIds();
// First delete matches that reference players
await prisma.match.deleteMany({
where: {
OR: [
{ player1P1Id: { in: await getEloTestPlayerIds() } },
{ player1P2Id: { in: await getEloTestPlayerIds() } },
{ player2P1Id: { in: await getEloTestPlayerIds() } },
{ player2P2Id: { in: await getEloTestPlayerIds() } },
{ player1P1Id: { in: playerIds } },
{ player1P2Id: { in: playerIds } },
{ player2P1Id: { in: playerIds } },
{ player2P2Id: { in: playerIds } },
]
}
});
// Then delete event participants that reference players
await prisma.eventParticipant.deleteMany({
where: {
playerId: { in: playerIds }
}
});
// Then delete partnerships
await prisma.partnershipStat.deleteMany({
where: {
OR: [
{ player1Id: { in: await getEloTestPlayerIds() } },
{ player2Id: { in: await getEloTestPlayerIds() } },
{ player1Id: { in: playerIds } },
{ player2Id: { in: playerIds } },
]
}
});
+2 -2
View File
@@ -17,8 +17,8 @@ test.describe('Epic 3: Rankings Page', () => {
test('Rankings page loads and displays rankings table', async ({ page }) => {
await page.goto('/rankings');
// Check page title or heading
await expect(page.locator('h1, h2')).toContainText(/rankings?/i);
// Check page title or heading - use .first() since page may have both h1 and h2
await expect(page.locator('h1, h2').first()).toContainText(/rankings?/i);
// Check for rankings table
await expect(page.locator('table')).toBeVisible();
+8 -1
View File
@@ -110,9 +110,16 @@ test.describe.serial('Epic 4: Tournament Creation', () => {
await page.goto('/admin/tournaments/new');
// Check for required fields
// Wait for step 1 form to load
await page.waitForSelector('input[name="name"]', { timeout: 10000 });
// Check for required fields on Step 1
await expect(page.locator('input[name="name"]')).toBeVisible();
await expect(page.locator('select[name="format"]')).toBeVisible();
// Step through to Step 2 to check for submit button (only appears after clicking Next)
await page.click('button:has-text("Next")');
await page.waitForSelector('button[type="submit"]', { timeout: 10000 });
await expect(page.locator('button[type="submit"]')).toBeVisible();
});
+2 -2
View File
@@ -138,8 +138,8 @@ test.describe.serial('Issue #7: Schedule Tab', () => {
// Navigate to tournament detail
await page.goto(`/admin/tournaments/${tournamentId}`);
// Check Schedule tab link exists
const scheduleLink = page.locator('a', { hasText: 'Schedule' });
// Check Schedule tab link exists - use button since page uses buttons for tabs
const scheduleLink = page.locator('button', { hasText: 'Schedule' });
await expect(scheduleLink).toBeVisible();
});
+2 -1
View File
@@ -126,7 +126,8 @@ test.describe.serial('Issue #22: Team Configuration', () => {
const playerName3 = `Player ${Date.now() + 2}`;
const playerName4 = `Player ${Date.now() + 3}`;
// Create first player
// Create first player - wait for search input to appear first
await page.waitForSelector('input[placeholder*="Search"]', { timeout: 10000 });
await page.fill('input[placeholder*="Search"]', playerName1);
await page.waitForTimeout(500);
await page.click(`text=+ Create "${playerName1}" as new player`);
+4 -4
View File
@@ -45,8 +45,8 @@ test.describe('Tournament Edit - allowTies functionality', () => {
// Navigate to tournament edit page
await page.goto(`/admin/tournaments/${tournamentId}/edit`);
// Wait for form to load
await expect(page.locator('text=Tournament Name')).toBeVisible();
// Wait for form to load - edit page shows "Edit Tournament" heading
await expect(page.locator('text=Edit Tournament')).toBeVisible();
// Check that allowTies checkbox exists
const allowTiesCheckbox = page.locator('input[name="allowTies"]');
@@ -59,7 +59,7 @@ test.describe('Tournament Edit - allowTies functionality', () => {
await page.goto(`/admin/tournaments/${tournamentId}/edit`);
// Wait for form to load
await expect(page.locator('text=Tournament Name')).toBeVisible();
await expect(page.locator('text=Edit Tournament')).toBeVisible();
// Toggle allowTies checkbox
const allowTiesCheckbox = page.locator('input[name="allowTies"]');
@@ -91,7 +91,7 @@ test.describe('Tournament Edit - allowTies functionality', () => {
await page.goto(`/admin/tournaments/${tournamentId}/edit`);
// Wait for form to load
await expect(page.locator('text=Tournament Name')).toBeVisible();
await expect(page.locator('text=Edit Tournament')).toBeVisible();
// Verify checkbox is checked
const allowTiesCheckbox = page.locator('input[name="allowTies"]');