Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a0872d07ef | |||
| feca7067b8 | |||
| f34dc23661 | |||
| f16ad054dd |
@@ -40,12 +40,12 @@ jobs:
|
||||
|
||||
# Wait for production site to be healthy
|
||||
echo "Waiting for production site to be healthy..."
|
||||
for i in {1..30}; do
|
||||
for i in {1..6}; do
|
||||
if curl -sf https://euchre.notsosm.art/api/health > /dev/null 2>&1; then
|
||||
echo "✅ Production successfully deployed with version ${VERSION}"
|
||||
exit 0
|
||||
fi
|
||||
sleep 0.5
|
||||
sleep 15
|
||||
done
|
||||
echo "❌ Production deployment failed"
|
||||
docker compose logs app
|
||||
|
||||
@@ -83,14 +83,16 @@ jobs:
|
||||
|
||||
- name: Wait for CI site to be ready
|
||||
run: |
|
||||
for i in {1..15}; do
|
||||
if docker ps --filter name=euchre-camp-ci --format '{{.Status}}' | grep -q Up; then
|
||||
echo "CI site container is running"
|
||||
echo "Waiting for Next.js to start..."
|
||||
sleep 20
|
||||
for i in {1..6}; do
|
||||
if curl -sf https://euchre-ci.notsosm.art/api/health > /dev/null 2>&1; then
|
||||
echo "CI site is healthy"
|
||||
exit 0
|
||||
fi
|
||||
sleep 2
|
||||
sleep 15
|
||||
done
|
||||
echo "CI site container failed to start"
|
||||
echo "CI site failed to become healthy after 90 seconds"
|
||||
docker compose -f /apps/euchre_camp_ci/docker-compose.yml logs app
|
||||
exit 1
|
||||
|
||||
|
||||
@@ -177,12 +177,12 @@ jobs:
|
||||
|
||||
# Wait for container to be healthy
|
||||
echo "Waiting for dev site to be healthy..."
|
||||
for i in {1..30}; do
|
||||
for i in {1..6}; do
|
||||
if curl -sf https://euchre-dev.notsosm.art/api/health > /dev/null 2>&1; then
|
||||
echo "✅ Dev environment successfully deployed with version ${{ steps.version.outputs.new_version }}"
|
||||
exit 0
|
||||
fi
|
||||
sleep 0.5
|
||||
sleep 15
|
||||
done
|
||||
echo "❌ Dev environment deployment failed"
|
||||
docker compose logs app
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -17,7 +17,7 @@ module.exports = {
|
||||
|
||||
// Format options
|
||||
format: [
|
||||
'progress-bar',
|
||||
process.env.CI ? 'progress' : 'progress-bar',
|
||||
'pretty:cucumber-pretty'
|
||||
],
|
||||
|
||||
|
||||
+30
-12
@@ -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 } },
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
|
||||
@@ -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`);
|
||||
|
||||
@@ -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"]');
|
||||
|
||||
@@ -259,12 +259,12 @@ deploy-prod version:
|
||||
docker compose pull app && \
|
||||
docker compose up -d app && \
|
||||
echo "Waiting for production site to be healthy..." && \
|
||||
for i in {1..30}; do \
|
||||
for i in {1..6}; do \
|
||||
if curl -sf https://euchre.notsosm.art/api/health > /dev/null 2>&1; then \
|
||||
echo "✅ Production successfully deployed with version {{version}}"; \
|
||||
exit 0; \
|
||||
fi; \
|
||||
sleep 0.5; \
|
||||
sleep 15; \
|
||||
done && \
|
||||
echo "❌ Production deployment failed - health check timed out"; \
|
||||
docker compose logs app; \
|
||||
|
||||
Reference in New Issue
Block a user