28fecdfaad
- Remove database provider switching logic from prisma.ts and auth.ts - Hardcode PostgreSQL as the only supported database - Remove switch-database.js and use-dev-db.js scripts - Remove Python utility scripts that used sqlite3 directly - Update justfile to remove SQLite test targets - Update package.json to remove db:switch script - Update Dockerfile.ci-base to default to PostgreSQL - Update .env.example to remove SQLite mention - Update playwright.config.ts comments - Update .gitignore to remove SQLite file patterns This eliminates the root cause of test failures: the dev server and test Prisma client were using different databases (PostgreSQL vs SQLite).
695 lines
23 KiB
TypeScript
695 lines
23 KiB
TypeScript
/**
|
|
* Authentication step definitions for EuchreCamp E2E tests
|
|
*
|
|
* These steps interact ONLY with the browser UI - no direct database access.
|
|
* All user creation happens via the registration/login UI.
|
|
*/
|
|
|
|
import { Given, When, Then } from '@cucumber/cucumber';
|
|
import { expect } from '@playwright/test';
|
|
import { world } from '../support/world';
|
|
|
|
// Generate unique test credentials
|
|
function generateTestCredentials() {
|
|
const timestamp = Date.now();
|
|
return {
|
|
email: `cucumber-test-${timestamp}@example.com`,
|
|
password: 'TestPassword1234!',
|
|
name: `Cucumber Test User ${timestamp}`
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Precondition: I am logged in as a player
|
|
* Creates a new user via the registration UI
|
|
*/
|
|
Given('I am logged in as a player', async function () {
|
|
console.log('🌍 Creating and logging in as a player via UI...');
|
|
|
|
// Generate unique credentials for each test run
|
|
const timestamp = Date.now();
|
|
const credentials = {
|
|
email: `cucumber-player-${timestamp}@example.com`,
|
|
password: 'TestPassword1234!', // 16+ characters for minPasswordLength=8
|
|
name: `Cucumber Player ${timestamp}`,
|
|
};
|
|
|
|
world.user = credentials;
|
|
|
|
// Start monitoring network requests
|
|
const requests: string[] = [];
|
|
const responses: string[] = [];
|
|
const consoleLogs: string[] = [];
|
|
world.page.on('request', req => requests.push(`${req.method()} ${req.url()}`));
|
|
world.page.on('response', res => responses.push(`${res.status()} ${res.url()}`));
|
|
world.page.on('console', msg => consoleLogs.push(`${msg.type()}: ${msg.text()}`));
|
|
world.page.on('pageerror', err => console.log('🌍 Page error:', err));
|
|
world.page.on('crash', () => console.log('🌍 Page crashed'));
|
|
|
|
// Navigate to registration page
|
|
await world.page.goto(`${world.baseURL}/auth/register`);
|
|
await world.page.waitForLoadState('domcontentloaded');
|
|
|
|
// Fill registration form
|
|
await world.page.fill('input[name="name"]', credentials.name);
|
|
await world.page.fill('input[name="email"]', credentials.email);
|
|
await world.page.fill('input[name="password"]', credentials.password);
|
|
|
|
// Submit form
|
|
await world.page.click('button[type="submit"]');
|
|
|
|
// Wait for redirect to profile page (using waitForURL which is more reliable)
|
|
// Timeout is high (60s) to accommodate slow dev server (HMR, etc.)
|
|
try {
|
|
console.log('🌍 Waiting for redirect to profile page...');
|
|
await world.page.waitForURL(/\/players\/\d+\/profile/, { timeout: 60000 });
|
|
console.log(`🌍 Player registered and redirected to profile: ${credentials.email}`);
|
|
|
|
// Extract player ID from URL for later use (e.g., schedule page)
|
|
const currentUrl = world.page.url();
|
|
const match = currentUrl.match(/\/players\/(\d+)\/profile/);
|
|
if (match) {
|
|
world.playerId = match[1];
|
|
console.log(`🌍 Extracted player ID: ${world.playerId}`);
|
|
}
|
|
} catch (e) {
|
|
console.log('🌍 Registration redirect did not complete as expected');
|
|
console.log(`🌍 Current URL: ${world.page.url()}`);
|
|
console.log('🌍 Recent requests:', requests.slice(-10));
|
|
console.log('🌍 Recent responses:', responses.slice(-10));
|
|
console.log('🌍 Browser console logs:', consoleLogs.slice(-10));
|
|
// Debug: dump page content
|
|
const content = await world.page.content();
|
|
console.log('🌍 Page content (first 500 chars):', content.substring(0, 500));
|
|
}
|
|
|
|
// Verify we're logged in by checking for sign-out button
|
|
// Use a more specific locator for the button
|
|
try {
|
|
const signOutButton = world.page.locator('button:has-text("Sign out")');
|
|
await expect(signOutButton).toBeVisible({ timeout: 10000 });
|
|
console.log(`🌍 Login verified on profile page: ${credentials.email}`);
|
|
} catch (e) {
|
|
console.log('🌍 Sign out button not visible on profile, trying home page...');
|
|
await world.page.goto(`${world.baseURL}/`);
|
|
await world.page.waitForLoadState('domcontentloaded');
|
|
try {
|
|
const signOutButton = world.page.locator('button:has-text("Sign out")');
|
|
await expect(signOutButton).toBeVisible({ timeout: 10000 });
|
|
console.log(`🌍 Login verified on home page: ${credentials.email}`);
|
|
} catch (e2) {
|
|
console.log('🌍 Could not verify login status');
|
|
}
|
|
}
|
|
|
|
console.log(`🌍 Player created: ${credentials.email}`);
|
|
});
|
|
|
|
/**
|
|
* Precondition: I am logged in as a tournament admin
|
|
* Note: In the actual app, admin roles are assigned by club admins or via API.
|
|
* For acceptance tests, we'll assign the tournament_admin role directly via Prisma.
|
|
*/
|
|
Given('I am logged in as a tournament admin', async function () {
|
|
console.log('🌍 Creating and logging in as a tournament admin...');
|
|
|
|
const credentials = generateTestCredentials();
|
|
world.user = credentials;
|
|
|
|
await world.page.goto(`${world.baseURL}/auth/register`);
|
|
await world.page.waitForLoadState('domcontentloaded');
|
|
|
|
await world.page.fill('input[name="name"]', credentials.name);
|
|
await world.page.fill('input[name="email"]', credentials.email);
|
|
await world.page.fill('input[name="password"]', credentials.password);
|
|
|
|
await world.page.click('button[type="submit"]');
|
|
|
|
// Wait for any redirect away from register page
|
|
await world.page.waitForURL((url) => !url.toString().includes('/auth/register'), { timeout: 15000 });
|
|
await world.page.waitForLoadState('networkidle');
|
|
await world.page.waitForTimeout(1000);
|
|
|
|
const currentUrl = world.page.url();
|
|
console.log(`🌍 After registration, URL: ${currentUrl}`);
|
|
|
|
// Try to extract player ID from URL
|
|
const match = currentUrl.match(/\/players\/(\d+)\/profile/);
|
|
if (match) {
|
|
world.playerId = match[1];
|
|
console.log(`🌍 Player ID from URL: ${world.playerId}`);
|
|
}
|
|
|
|
// Get the user ID from the database (works regardless of redirect destination)
|
|
const prisma = await world.getPrisma();
|
|
console.log(`🌍 Looking up user by email: ${credentials.email}`);
|
|
const user = await prisma.user.findUnique({
|
|
where: { email: credentials.email },
|
|
include: { player: true }
|
|
});
|
|
|
|
if (user) {
|
|
(world.user as any).id = user.id;
|
|
console.log(`🌍 User ID from DB: ${user.id}, role: ${user.role}, playerId: ${user.playerId}`);
|
|
|
|
if (user.player) {
|
|
world.playerId = user.player.id.toString();
|
|
console.log(`🌍 Player ID from DB: ${world.playerId}`);
|
|
}
|
|
|
|
// Assign tournament_admin role
|
|
await prisma.user.update({
|
|
where: { id: user.id },
|
|
data: { role: 'tournament_admin' }
|
|
});
|
|
console.log(`🌍 Assigned tournament_admin role to user: ${user.id}`);
|
|
|
|
// Navigate to trigger a fresh role fetch
|
|
await world.page.goto(`${world.baseURL}/rankings`);
|
|
await world.page.waitForLoadState('networkidle');
|
|
await world.page.waitForTimeout(500);
|
|
} else {
|
|
console.log(`🌍 WARNING: User not found in DB by email. Trying to find latest user...`);
|
|
// Fallback: find the latest user (most recently created)
|
|
const latestUser = await prisma.user.findFirst({
|
|
orderBy: { createdAt: 'desc' },
|
|
include: { player: true }
|
|
});
|
|
if (latestUser) {
|
|
(world.user as any).id = latestUser.id;
|
|
world.playerId = latestUser.playerId?.toString() || latestUser.player?.id?.toString();
|
|
console.log(`🌍 Using latest user: ${latestUser.id} (${latestUser.email})`);
|
|
|
|
await prisma.user.update({
|
|
where: { id: latestUser.id },
|
|
data: { role: 'tournament_admin' }
|
|
});
|
|
console.log(`🌍 Assigned tournament_admin role`);
|
|
}
|
|
}
|
|
|
|
console.log(`🌍 User created: ${credentials.email}`);
|
|
});
|
|
|
|
/**
|
|
* Precondition: I am logged in as a site admin
|
|
* Creates a new user and assigns site_admin role via Prisma
|
|
*/
|
|
Given('I am logged in as a site admin', async function () {
|
|
console.log('🌍 Creating and logging in as a site admin...');
|
|
|
|
const credentials = generateTestCredentials();
|
|
world.user = credentials;
|
|
|
|
await world.page.goto(`${world.baseURL}/auth/register`);
|
|
await world.page.waitForLoadState('domcontentloaded');
|
|
|
|
await world.page.fill('input[name="name"]', credentials.name);
|
|
await world.page.fill('input[name="email"]', credentials.email);
|
|
await world.page.fill('input[name="password"]', credentials.password);
|
|
|
|
await world.page.click('button[type="submit"]');
|
|
await world.page.waitForURL(/\/players\/\d+\/profile/, { timeout: 15000 });
|
|
|
|
const currentUrl = world.page.url();
|
|
const match = currentUrl.match(/\/players\/(\d+)\/profile/);
|
|
if (match) {
|
|
const playerId = match[1];
|
|
world.playerId = playerId;
|
|
|
|
const prisma = await world.getPrisma();
|
|
const player = await prisma.player.findUnique({
|
|
where: { id: parseInt(playerId) },
|
|
include: { user: true }
|
|
});
|
|
|
|
if (player && player.user) {
|
|
const userId = player.user.id;
|
|
(world.user as any).id = userId;
|
|
|
|
await prisma.user.update({
|
|
where: { id: userId },
|
|
data: { role: 'site_admin' }
|
|
});
|
|
console.log(`🌍 Assigned site_admin role to user: ${userId}`);
|
|
|
|
// Navigate to home page to trigger Navigation re-mount with new role
|
|
await world.page.goto(`${world.baseURL}/`);
|
|
await world.page.waitForLoadState('networkidle');
|
|
await world.page.waitForTimeout(1000);
|
|
}
|
|
}
|
|
|
|
console.log(`🌍 Site admin created: ${credentials.email}`);
|
|
});
|
|
|
|
/**
|
|
* Precondition: I am logged in as a club admin
|
|
* Uses a pre-existing admin user from the database
|
|
*/
|
|
Given('I am logged in as a club admin', async function () {
|
|
console.log('🌍 Logging in as existing club admin...');
|
|
|
|
// Use the admin user created by seed.js
|
|
const adminEmail = 'david@dhg.lol';
|
|
const adminPassword = 'adminadmin';
|
|
|
|
world.user = {
|
|
email: adminEmail,
|
|
password: adminPassword,
|
|
name: 'David Admin',
|
|
};
|
|
|
|
await world.page.goto(`${world.baseURL}/auth/login`);
|
|
await world.page.waitForLoadState('domcontentloaded');
|
|
|
|
await world.page.fill('input[name="email"]', adminEmail);
|
|
await world.page.fill('input[name="password"]', adminPassword);
|
|
await world.page.click('button[type="submit"]');
|
|
|
|
// Wait for redirect after login
|
|
try {
|
|
await world.page.waitForURL((url) => !url.toString().includes('/auth/login'), { timeout: 10000 });
|
|
console.log(`🌍 Club admin logged in: ${adminEmail}`);
|
|
} catch (e) {
|
|
console.log('🌍 Login redirect timed out, current URL:', world.page.url());
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Registration steps (UI-only)
|
|
*/
|
|
When('I register with valid credentials', async function () {
|
|
const credentials = generateTestCredentials();
|
|
world.user = credentials;
|
|
|
|
await world.page.goto(`${world.baseURL}/auth/register`);
|
|
await world.page.waitForLoadState('domcontentloaded');
|
|
|
|
await world.page.fill('input[name="name"]', credentials.name);
|
|
await world.page.fill('input[name="email"]', credentials.email);
|
|
await world.page.fill('input[name="password"]', credentials.password);
|
|
|
|
await world.page.click('button[type="submit"]');
|
|
|
|
console.log(`🌍 Registered with credentials: ${credentials.email}`);
|
|
});
|
|
|
|
When('I register with duplicate email', async function () {
|
|
if (!world.user) {
|
|
throw new Error('No existing user to duplicate');
|
|
}
|
|
|
|
await world.page.goto(`${world.baseURL}/auth/register`);
|
|
await world.page.waitForLoadState('domcontentloaded');
|
|
|
|
await world.page.fill('input[name="name"]', world.user.name);
|
|
await world.page.fill('input[name="email"]', world.user.email);
|
|
await world.page.fill('input[name="password"]', world.user.password);
|
|
|
|
await world.page.click('button[type="submit"]');
|
|
|
|
console.log(`🌍 Attempted registration with duplicate: ${world.user.email}`);
|
|
});
|
|
|
|
When('I fill in {string} with the same email', async function (fieldName: string) {
|
|
if (!world.user) {
|
|
throw new Error('No user credentials available');
|
|
}
|
|
|
|
const selector = `input[name="email"]`;
|
|
console.log(`🌍 Filling ${fieldName} with same email: ${world.user.email}`);
|
|
await world.page.fill(selector, world.user.email);
|
|
});
|
|
|
|
When('I register with weak password', async function () {
|
|
const credentials = generateTestCredentials();
|
|
credentials.password = 'weak'; // Too short
|
|
|
|
await world.page.goto(`${world.baseURL}/auth/register`);
|
|
await world.page.waitForLoadState('domcontentloaded');
|
|
|
|
await world.page.fill('input[name="name"]', credentials.name);
|
|
await world.page.fill('input[name="email"]', credentials.email);
|
|
await world.page.fill('input[name="password"]', credentials.password);
|
|
|
|
await world.page.click('button[type="submit"]');
|
|
|
|
console.log('🌍 Attempted registration with weak password');
|
|
});
|
|
|
|
/**
|
|
* Login steps (UI-only)
|
|
*/
|
|
When('I log in with valid credentials', async function () {
|
|
if (!world.user) {
|
|
throw new Error('No user credentials available');
|
|
}
|
|
|
|
await world.page.goto(`${world.baseURL}/auth/login`);
|
|
await world.page.waitForLoadState('domcontentloaded');
|
|
|
|
await world.page.fill('input[name="email"]', world.user.email);
|
|
await world.page.fill('input[name="password"]', world.user.password);
|
|
|
|
await world.page.click('button[type="submit"]');
|
|
|
|
console.log(`🌍 Logged in as: ${world.user.email}`);
|
|
});
|
|
|
|
When('I log in with invalid credentials', async function () {
|
|
await world.page.goto(`${world.baseURL}/auth/login`);
|
|
await world.page.waitForLoadState('domcontentloaded');
|
|
|
|
await world.page.fill('input[name="email"]', 'nonexistent@example.com');
|
|
await world.page.fill('input[name="password"]', 'wrongpassword');
|
|
|
|
await world.page.click('button[type="submit"]');
|
|
|
|
console.log('🌍 Attempted login with invalid credentials');
|
|
});
|
|
|
|
/**
|
|
* Logout steps (UI-only)
|
|
*/
|
|
When('I log out', async function () {
|
|
// Click on logout button
|
|
await world.page.click('text=Sign out');
|
|
|
|
console.log('🌍 Logged out');
|
|
});
|
|
|
|
/**
|
|
* Note: The step "I am logged in as a player" is already defined at line 26
|
|
*/
|
|
|
|
Then('I should not be logged in', async function () {
|
|
// Check that we're on login page or don't see logout button
|
|
const currentUrl = world.page.url();
|
|
expect(currentUrl).toContain('/auth/login');
|
|
console.log('🌍 Verified user is not logged in');
|
|
});
|
|
|
|
Then('I should see a registration error', async function () {
|
|
// Check for error message in page content
|
|
const content = await world.page.content();
|
|
expect(content).toContain('error');
|
|
console.log('🌍 Verified registration error is visible');
|
|
});
|
|
|
|
Then('I should see an error message', async function () {
|
|
// Check for any error message on the page
|
|
const content = await world.page.content();
|
|
expect(content).toMatch(/error|Error/i);
|
|
console.log('🌍 Verified error message is visible');
|
|
});
|
|
|
|
Then('I should remain on the login page', async function () {
|
|
const currentUrl = world.page.url();
|
|
expect(currentUrl).toContain('/auth/login');
|
|
console.log('🌍 Verified still on login page');
|
|
});
|
|
|
|
Then('I should remain on the registration page', async function () {
|
|
const currentUrl = world.page.url();
|
|
expect(currentUrl).toContain('/auth/register');
|
|
console.log('🌍 Verified still on registration page');
|
|
});
|
|
|
|
/**
|
|
* Helper: Verify user was created via UI (no database check)
|
|
*/
|
|
Then('my user account should exist', async function () {
|
|
if (!world.user) {
|
|
throw new Error('No user credentials available');
|
|
}
|
|
|
|
// We can't check the database directly in acceptance tests
|
|
// Instead, verify we're logged in (user profile page)
|
|
await expect(world.page.locator('text=Welcome')).toBeVisible();
|
|
console.log('🌍 Verified user account was created successfully');
|
|
});
|
|
|
|
/**
|
|
* Schedule steps (player)
|
|
*/
|
|
When('I go to my schedule page', async function () {
|
|
console.log('🌍 Going to schedule page');
|
|
// Navigate to the schedule page using the extracted player ID
|
|
if (!world.playerId) {
|
|
throw new Error('Player ID not found. Ensure "I am logged in as a player" was run first.');
|
|
}
|
|
await world.page.goto(`${world.baseURL}/players/${world.playerId}/schedule`);
|
|
await world.page.waitForLoadState('domcontentloaded');
|
|
});
|
|
|
|
Given('I have upcoming matches in my schedule', async function () {
|
|
console.log('🌍 Setting up upcoming matches in schedule');
|
|
const prisma = await world.getPrisma();
|
|
const timestamp = Date.now();
|
|
|
|
// Get the current player
|
|
if (!world.playerId) {
|
|
throw new Error('No player ID found. Make sure user is logged in as a player first.');
|
|
}
|
|
|
|
const currentPlayerId = parseInt(world.playerId, 10);
|
|
|
|
// Create 3 other players for the match
|
|
const opponent1 = await prisma.player.create({
|
|
data: {
|
|
name: `Opponent ${timestamp} 1`,
|
|
normalizedName: `opponent ${timestamp} 1`,
|
|
currentElo: 1000,
|
|
},
|
|
});
|
|
|
|
const opponent2 = await prisma.player.create({
|
|
data: {
|
|
name: `Opponent ${timestamp} 2`,
|
|
normalizedName: `opponent ${timestamp} 2`,
|
|
currentElo: 1000,
|
|
},
|
|
});
|
|
|
|
const partner1 = await prisma.player.create({
|
|
data: {
|
|
name: `Partner ${timestamp}`,
|
|
normalizedName: `partner ${timestamp}`,
|
|
currentElo: 1000,
|
|
},
|
|
});
|
|
|
|
// Create a tournament
|
|
const tournament = await prisma.event.create({
|
|
data: {
|
|
name: `Test Schedule Tournament ${timestamp}`,
|
|
eventDate: new Date(Date.now() + 86400000), // Tomorrow
|
|
status: 'planned',
|
|
},
|
|
});
|
|
|
|
// Create a match with the current player as player1P1 (played tomorrow)
|
|
await prisma.match.create({
|
|
data: {
|
|
eventId: tournament.id,
|
|
player1P1Id: currentPlayerId,
|
|
player1P2Id: partner1.id,
|
|
player2P1Id: opponent1.id,
|
|
player2P2Id: opponent2.id,
|
|
team1Score: 10,
|
|
team2Score: 5,
|
|
status: 'completed',
|
|
playedAt: new Date(Date.now() + 86400000), // Tomorrow
|
|
},
|
|
});
|
|
|
|
console.log(`🌍 Created tournament "${tournament.name}" with 1 match for player ${currentPlayerId}`);
|
|
});
|
|
|
|
/**
|
|
* Tournament schedule steps
|
|
*/
|
|
Given('a tournament exists with {int} teams', async function (teamCount: number) {
|
|
console.log(`🌍 Setting up tournament with ${teamCount} teams`);
|
|
|
|
// Get Prisma client
|
|
const prisma = await world.getPrisma();
|
|
const timestamp = Date.now();
|
|
|
|
// Get the current user ID for ownership
|
|
const userId = world.user?.id;
|
|
if (!userId) {
|
|
throw new Error('User ID not found. Ensure user is logged in before creating tournament.');
|
|
}
|
|
|
|
// Always create a new tournament for test isolation
|
|
const tournament = await prisma.event.create({
|
|
data: {
|
|
name: `Test Tournament ${timestamp}`,
|
|
createdAt: new Date(),
|
|
ownerId: userId, // Set the owner to the current user
|
|
},
|
|
});
|
|
|
|
// Euchre is 2v2, so each team has 2 players
|
|
// Create teamCount * 2 players and add them as participants
|
|
const playerCount = teamCount * 2;
|
|
for (let i = 1; i <= playerCount; i++) {
|
|
const player = await prisma.player.create({
|
|
data: {
|
|
name: `Tournament Player ${i} ${timestamp}`,
|
|
normalizedName: `tournament player ${i} ${timestamp}`,
|
|
currentElo: 1000,
|
|
gamesPlayed: 0,
|
|
wins: 0,
|
|
losses: 0,
|
|
},
|
|
});
|
|
|
|
await prisma.eventParticipant.create({
|
|
data: {
|
|
eventId: tournament.id,
|
|
playerId: player.id,
|
|
},
|
|
});
|
|
}
|
|
|
|
world.tournament = tournament;
|
|
world.tournamentTeamCount = teamCount;
|
|
|
|
console.log(`🌍 Created tournament: ${tournament.name} (ID: ${tournament.id}) with ${playerCount} players (${teamCount} teams)`);
|
|
});
|
|
|
|
When('I go to the tournament schedule page', async function () {
|
|
console.log('🌍 Going to tournament schedule page');
|
|
const tournamentId = world.tournament?.id || 1;
|
|
await world.page.goto(`${world.baseURL}/admin/tournaments/${tournamentId}/schedule`);
|
|
await world.page.waitForLoadState('load');
|
|
// Wait for client components to hydrate
|
|
await world.page.waitForTimeout(1000);
|
|
});
|
|
|
|
Given('a tournament has a generated schedule', async function () {
|
|
console.log('🌍 Creating tournament with generated schedule');
|
|
|
|
const prisma = await world.getPrisma();
|
|
const timestamp = Date.now();
|
|
|
|
// Get the current user ID for ownership
|
|
const userId = world.user?.id;
|
|
if (!userId) {
|
|
throw new Error('User ID not found. Ensure user is logged in before creating tournament.');
|
|
}
|
|
|
|
// Create a tournament
|
|
const tournament = await prisma.event.create({
|
|
data: {
|
|
name: `Test Schedule Tournament ${timestamp}`,
|
|
createdAt: new Date(),
|
|
ownerId: userId, // Set the owner to the current user
|
|
},
|
|
});
|
|
|
|
// Create 4 players and add them as participants
|
|
const players = [];
|
|
for (let i = 1; i <= 4; i++) {
|
|
const player = await prisma.player.create({
|
|
data: {
|
|
name: `Schedule Player ${i} ${timestamp}`,
|
|
normalizedName: `schedule player ${i} ${timestamp}`,
|
|
currentElo: 1000,
|
|
gamesPlayed: 0,
|
|
wins: 0,
|
|
losses: 0,
|
|
},
|
|
});
|
|
players.push(player);
|
|
|
|
await prisma.eventParticipant.create({
|
|
data: {
|
|
eventId: tournament.id,
|
|
playerId: player.id,
|
|
},
|
|
});
|
|
}
|
|
|
|
// Generate schedule via API
|
|
const response = await fetch(`${world.baseURL}/api/tournaments/${tournament.id}/schedule`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
});
|
|
|
|
if (!response.ok) {
|
|
console.log('🌍 Failed to generate schedule:', response.status, response.statusText);
|
|
// Try to get error details
|
|
try {
|
|
const errorData = await response.json();
|
|
console.log('🌍 Error details:', errorData);
|
|
} catch {
|
|
// Ignore
|
|
}
|
|
} else {
|
|
const data = await response.json();
|
|
console.log('🌍 Schedule generated:', data);
|
|
}
|
|
|
|
world.tournament = tournament;
|
|
world.tournamentTeamCount = 4;
|
|
console.log(`🌍 Tournament with schedule created: ${tournament.name} (ID: ${tournament.id})`);
|
|
});
|
|
|
|
Given('there are recent activities in the system', async function () {
|
|
// Create test activities using the activity logger
|
|
const prisma = await world.getPrisma()
|
|
|
|
// Use timestamp to ensure unique names
|
|
const timestamp = Date.now()
|
|
|
|
// Create a test player first
|
|
const player = await prisma.player.create({
|
|
data: {
|
|
name: `Test Activity Player ${timestamp}`,
|
|
normalizedName: `test activity player ${timestamp}`,
|
|
currentElo: 1000,
|
|
gamesPlayed: 0,
|
|
wins: 0,
|
|
losses: 0,
|
|
},
|
|
})
|
|
|
|
// Create an activity
|
|
await (prisma as any).activity.create({
|
|
data: {
|
|
type: 'player_registration',
|
|
description: `Test Activity Player ${timestamp} registered`,
|
|
playerId: player.id,
|
|
},
|
|
})
|
|
|
|
console.log('🌍 Created test activity for player:', player.name)
|
|
})
|
|
|
|
Given('there are multiple players in the system', async function () {
|
|
const prisma = await world.getPrisma()
|
|
|
|
// Use timestamp to ensure unique names
|
|
const timestamp = Date.now()
|
|
|
|
// Create multiple test players
|
|
for (let i = 1; i <= 5; i++) {
|
|
await prisma.player.create({
|
|
data: {
|
|
name: `Test Player ${i} ${timestamp}`,
|
|
normalizedName: `test player ${i} ${timestamp}`,
|
|
currentElo: 1000 + i * 10,
|
|
gamesPlayed: 0,
|
|
wins: 0,
|
|
losses: 0,
|
|
},
|
|
})
|
|
}
|
|
|
|
console.log('🌍 Created 5 test players')
|
|
})
|