fix: resolve remaining test failures in CI
- 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:
@@ -13,6 +13,7 @@ import path from 'path';
|
|||||||
test.describe('CSV Upload Player Deduplication', () => {
|
test.describe('CSV Upload Player Deduplication', () => {
|
||||||
let testTournamentId: number;
|
let testTournamentId: number;
|
||||||
const testPlayerIds: number[] = [];
|
const testPlayerIds: number[] = [];
|
||||||
|
const ts = Date.now();
|
||||||
|
|
||||||
test.beforeAll(async () => {
|
test.beforeAll(async () => {
|
||||||
// Create a test tournament
|
// 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({
|
await prisma.player.deleteMany({
|
||||||
where: {
|
where: {
|
||||||
name: {
|
OR: [
|
||||||
contains: 'Dedupe',
|
{ 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
|
// First, create some players manually to simulate previous uploads
|
||||||
const player1 = await prisma.player.create({
|
const player1 = await prisma.player.create({
|
||||||
data: {
|
data: {
|
||||||
name: 'Aggregate Test',
|
name: `Aggregate Test ${ts}`,
|
||||||
normalizedName: 'aggregate test',
|
normalizedName: `aggregate test ${ts}`,
|
||||||
currentElo: 1050,
|
currentElo: 1050,
|
||||||
gamesPlayed: 5,
|
gamesPlayed: 5,
|
||||||
wins: 3,
|
wins: 3,
|
||||||
@@ -175,7 +178,7 @@ test.describe('CSV Upload Player Deduplication', () => {
|
|||||||
|
|
||||||
// Upload a CSV with the same player name
|
// 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
|
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');
|
const csvPath = path.join(__dirname, 'temp-aggregate-test.csv');
|
||||||
fs.writeFileSync(csvPath, csvContent);
|
fs.writeFileSync(csvPath, csvContent);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ module.exports = {
|
|||||||
|
|
||||||
// Format options
|
// Format options
|
||||||
format: [
|
format: [
|
||||||
'progress-bar',
|
process.env.CI ? 'progress' : 'progress-bar',
|
||||||
'pretty:cucumber-pretty'
|
'pretty:cucumber-pretty'
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|||||||
+30
-12
@@ -13,24 +13,33 @@ import path from 'path';
|
|||||||
test.describe('Elo Rating Updates', () => {
|
test.describe('Elo Rating Updates', () => {
|
||||||
test.beforeAll(async () => {
|
test.beforeAll(async () => {
|
||||||
// Clean up any existing test data
|
// Clean up any existing test data
|
||||||
|
const playerIds = await getEloTestPlayerIds();
|
||||||
|
|
||||||
// First delete matches that reference players
|
// First delete matches that reference players
|
||||||
await prisma.match.deleteMany({
|
await prisma.match.deleteMany({
|
||||||
where: {
|
where: {
|
||||||
OR: [
|
OR: [
|
||||||
{ player1P1Id: { in: await getEloTestPlayerIds() } },
|
{ player1P1Id: { in: playerIds } },
|
||||||
{ player1P2Id: { in: await getEloTestPlayerIds() } },
|
{ player1P2Id: { in: playerIds } },
|
||||||
{ player2P1Id: { in: await getEloTestPlayerIds() } },
|
{ player2P1Id: { in: playerIds } },
|
||||||
{ player2P2Id: { in: await getEloTestPlayerIds() } },
|
{ player2P2Id: { in: playerIds } },
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Then delete event participants that reference players
|
||||||
|
await prisma.eventParticipant.deleteMany({
|
||||||
|
where: {
|
||||||
|
playerId: { in: playerIds }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Then delete partnerships
|
// Then delete partnerships
|
||||||
await prisma.partnershipStat.deleteMany({
|
await prisma.partnershipStat.deleteMany({
|
||||||
where: {
|
where: {
|
||||||
OR: [
|
OR: [
|
||||||
{ player1Id: { in: await getEloTestPlayerIds() } },
|
{ player1Id: { in: playerIds } },
|
||||||
{ player2Id: { in: await getEloTestPlayerIds() } },
|
{ player2Id: { in: playerIds } },
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -47,24 +56,33 @@ test.describe('Elo Rating Updates', () => {
|
|||||||
|
|
||||||
test.afterAll(async () => {
|
test.afterAll(async () => {
|
||||||
// Clean up test data
|
// Clean up test data
|
||||||
|
const playerIds = await getEloTestPlayerIds();
|
||||||
|
|
||||||
// First delete matches that reference players
|
// First delete matches that reference players
|
||||||
await prisma.match.deleteMany({
|
await prisma.match.deleteMany({
|
||||||
where: {
|
where: {
|
||||||
OR: [
|
OR: [
|
||||||
{ player1P1Id: { in: await getEloTestPlayerIds() } },
|
{ player1P1Id: { in: playerIds } },
|
||||||
{ player1P2Id: { in: await getEloTestPlayerIds() } },
|
{ player1P2Id: { in: playerIds } },
|
||||||
{ player2P1Id: { in: await getEloTestPlayerIds() } },
|
{ player2P1Id: { in: playerIds } },
|
||||||
{ player2P2Id: { in: await getEloTestPlayerIds() } },
|
{ player2P2Id: { in: playerIds } },
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Then delete event participants that reference players
|
||||||
|
await prisma.eventParticipant.deleteMany({
|
||||||
|
where: {
|
||||||
|
playerId: { in: playerIds }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Then delete partnerships
|
// Then delete partnerships
|
||||||
await prisma.partnershipStat.deleteMany({
|
await prisma.partnershipStat.deleteMany({
|
||||||
where: {
|
where: {
|
||||||
OR: [
|
OR: [
|
||||||
{ player1Id: { in: await getEloTestPlayerIds() } },
|
{ player1Id: { in: playerIds } },
|
||||||
{ player2Id: { in: await getEloTestPlayerIds() } },
|
{ player2Id: { in: playerIds } },
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ test.describe('Epic 3: Rankings Page', () => {
|
|||||||
test('Rankings page loads and displays rankings table', async ({ page }) => {
|
test('Rankings page loads and displays rankings table', async ({ page }) => {
|
||||||
await page.goto('/rankings');
|
await page.goto('/rankings');
|
||||||
|
|
||||||
// Check page title or heading
|
// Check page title or heading - use .first() since page may have both h1 and h2
|
||||||
await expect(page.locator('h1, h2')).toContainText(/rankings?/i);
|
await expect(page.locator('h1, h2').first()).toContainText(/rankings?/i);
|
||||||
|
|
||||||
// Check for rankings table
|
// Check for rankings table
|
||||||
await expect(page.locator('table')).toBeVisible();
|
await expect(page.locator('table')).toBeVisible();
|
||||||
|
|||||||
@@ -110,9 +110,16 @@ test.describe.serial('Epic 4: Tournament Creation', () => {
|
|||||||
|
|
||||||
await page.goto('/admin/tournaments/new');
|
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('input[name="name"]')).toBeVisible();
|
||||||
await expect(page.locator('select[name="format"]')).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();
|
await expect(page.locator('button[type="submit"]')).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -138,8 +138,8 @@ test.describe.serial('Issue #7: Schedule Tab', () => {
|
|||||||
// Navigate to tournament detail
|
// Navigate to tournament detail
|
||||||
await page.goto(`/admin/tournaments/${tournamentId}`);
|
await page.goto(`/admin/tournaments/${tournamentId}`);
|
||||||
|
|
||||||
// Check Schedule tab link exists
|
// Check Schedule tab link exists - use button since page uses buttons for tabs
|
||||||
const scheduleLink = page.locator('a', { hasText: 'Schedule' });
|
const scheduleLink = page.locator('button', { hasText: 'Schedule' });
|
||||||
await expect(scheduleLink).toBeVisible();
|
await expect(scheduleLink).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -126,7 +126,8 @@ test.describe.serial('Issue #22: Team Configuration', () => {
|
|||||||
const playerName3 = `Player ${Date.now() + 2}`;
|
const playerName3 = `Player ${Date.now() + 2}`;
|
||||||
const playerName4 = `Player ${Date.now() + 3}`;
|
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.fill('input[placeholder*="Search"]', playerName1);
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
await page.click(`text=+ Create "${playerName1}" as new player`);
|
await page.click(`text=+ Create "${playerName1}" as new player`);
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ test.describe('Tournament Edit - allowTies functionality', () => {
|
|||||||
// Navigate to tournament edit page
|
// Navigate to tournament edit page
|
||||||
await page.goto(`/admin/tournaments/${tournamentId}/edit`);
|
await page.goto(`/admin/tournaments/${tournamentId}/edit`);
|
||||||
|
|
||||||
// Wait for form to load
|
// Wait for form to load - edit page shows "Edit Tournament" heading
|
||||||
await expect(page.locator('text=Tournament Name')).toBeVisible();
|
await expect(page.locator('text=Edit Tournament')).toBeVisible();
|
||||||
|
|
||||||
// Check that allowTies checkbox exists
|
// Check that allowTies checkbox exists
|
||||||
const allowTiesCheckbox = page.locator('input[name="allowTies"]');
|
const allowTiesCheckbox = page.locator('input[name="allowTies"]');
|
||||||
@@ -59,7 +59,7 @@ test.describe('Tournament Edit - allowTies functionality', () => {
|
|||||||
await page.goto(`/admin/tournaments/${tournamentId}/edit`);
|
await page.goto(`/admin/tournaments/${tournamentId}/edit`);
|
||||||
|
|
||||||
// Wait for form to load
|
// Wait for form to load
|
||||||
await expect(page.locator('text=Tournament Name')).toBeVisible();
|
await expect(page.locator('text=Edit Tournament')).toBeVisible();
|
||||||
|
|
||||||
// Toggle allowTies checkbox
|
// Toggle allowTies checkbox
|
||||||
const allowTiesCheckbox = page.locator('input[name="allowTies"]');
|
const allowTiesCheckbox = page.locator('input[name="allowTies"]');
|
||||||
@@ -91,7 +91,7 @@ test.describe('Tournament Edit - allowTies functionality', () => {
|
|||||||
await page.goto(`/admin/tournaments/${tournamentId}/edit`);
|
await page.goto(`/admin/tournaments/${tournamentId}/edit`);
|
||||||
|
|
||||||
// Wait for form to load
|
// 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
|
// Verify checkbox is checked
|
||||||
const allowTiesCheckbox = page.locator('input[name="allowTies"]');
|
const allowTiesCheckbox = page.locator('input[name="allowTies"]');
|
||||||
|
|||||||
Reference in New Issue
Block a user