629 lines
24 KiB
TypeScript
629 lines
24 KiB
TypeScript
import { test, expect, Browser, APIRequestContext } from '@playwright/test';
|
|
import { WebsiteAuthManager, AuthContext } from '../../shared/website/WebsiteAuthManager';
|
|
import { ConsoleErrorCapture } from '../../shared/website/ConsoleErrorCapture';
|
|
import { WebsiteRouteManager } from '../../shared/website/WebsiteRouteManager';
|
|
|
|
/**
|
|
* E2E Tests for League Pages with Data Validation
|
|
*
|
|
* Tests cover:
|
|
* 1. /leagues (Discovery Page) - League cards, filters, quick actions
|
|
* 2. /leagues/[id] (Overview Page) - Stats, next race, season progress
|
|
* 3. /leagues/[id]/schedule (Schedule Page) - Race list, registration, admin controls
|
|
* 4. /leagues/[id]/standings (Standings Page) - Trend indicators, stats, team toggle
|
|
* 5. /leagues/[id]/roster (Roster Page) - Driver cards, admin actions
|
|
*/
|
|
|
|
test.describe('League Pages - E2E with Data Validation', () => {
|
|
const routeManager = new WebsiteRouteManager();
|
|
const leagueId = routeManager.resolvePathTemplate('/leagues/[id]', { id: WebsiteRouteManager.IDs.LEAGUE });
|
|
|
|
const CONSOLE_ALLOWLIST = [
|
|
/Download the React DevTools/i,
|
|
/Next.js-specific warning/i,
|
|
/Failed to load resource: the server responded with a status of 404/i,
|
|
/Failed to load resource: the server responded with a status of 403/i,
|
|
/Failed to load resource: the server responded with a status of 401/i,
|
|
/Failed to load resource: the server responded with a status of 500/i,
|
|
/net::ERR_NAME_NOT_RESOLVED/i,
|
|
/net::ERR_CONNECTION_CLOSED/i,
|
|
/net::ERR_ACCESS_DENIED/i,
|
|
/Minified React error #418/i,
|
|
/Event/i,
|
|
/An error occurred in the Server Components render/i,
|
|
/Route Error Boundary/i,
|
|
];
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
const allowedHosts = [
|
|
new URL(process.env.PLAYWRIGHT_BASE_URL || 'http://website:3000').host,
|
|
new URL(process.env.API_BASE_URL || 'http://api:3000').host,
|
|
];
|
|
|
|
await page.route('**/*', (route) => {
|
|
const url = new URL(route.request().url());
|
|
if (allowedHosts.includes(url.host) || url.protocol === 'data:') {
|
|
route.continue();
|
|
} else {
|
|
route.abort('accessdenied');
|
|
}
|
|
});
|
|
});
|
|
|
|
test.describe('1. /leagues (Discovery Page)', () => {
|
|
test('Unauthenticated user can view league discovery page', async ({ page }) => {
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
await page.goto('/leagues', { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Verify page loads successfully
|
|
expect(page.url()).toContain('/leagues');
|
|
|
|
// Verify featured leagues section displays
|
|
await expect(page.getByTestId('featured-leagues-section')).toBeVisible();
|
|
|
|
// Verify league cards are present
|
|
const leagueCards = page.getByTestId('league-card');
|
|
await expect(leagueCards.first()).toBeVisible();
|
|
|
|
// Verify league cards show correct metadata
|
|
const firstCard = leagueCards.first();
|
|
await expect(firstCard.getByTestId('league-card-title')).toBeVisible();
|
|
await expect(firstCard.getByTestId('league-card-next-race')).toBeVisible();
|
|
await expect(firstCard.getByTestId('league-card-active-drivers')).toBeVisible();
|
|
|
|
// Verify category filters are present
|
|
await expect(page.getByTestId('category-filters')).toBeVisible();
|
|
|
|
// Verify Quick Join/Follow buttons are present
|
|
await expect(page.getByTestId('quick-join-button')).toBeVisible();
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
});
|
|
|
|
test('Authenticated user can view league discovery page', async ({ browser, request }) => {
|
|
const { context, page } = await WebsiteAuthManager.createAuthContext(browser, request, 'auth');
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
try {
|
|
await page.goto('/leagues', { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Verify page loads successfully
|
|
expect(page.url()).toContain('/leagues');
|
|
|
|
// Verify featured leagues section displays
|
|
await expect(page.getByTestId('featured-leagues-section')).toBeVisible();
|
|
|
|
// Verify league cards are present
|
|
const leagueCards = page.getByTestId('league-card');
|
|
await expect(leagueCards.first()).toBeVisible();
|
|
|
|
// Verify league cards show correct metadata
|
|
const firstCard = leagueCards.first();
|
|
await expect(firstCard.getByTestId('league-card-title')).toBeVisible();
|
|
await expect(firstCard.getByTestId('league-card-next-race')).toBeVisible();
|
|
await expect(firstCard.getByTestId('league-card-active-drivers')).toBeVisible();
|
|
|
|
// Verify category filters are present
|
|
await expect(page.getByTestId('category-filters')).toBeVisible();
|
|
|
|
// Verify Quick Join/Follow buttons are present
|
|
await expect(page.getByTestId('quick-join-button')).toBeVisible();
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
} finally {
|
|
await context.close();
|
|
}
|
|
});
|
|
|
|
test('Category filters work correctly', async ({ page }) => {
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
await page.goto('/leagues', { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Verify category filters are present
|
|
await expect(page.getByTestId('category-filters')).toBeVisible();
|
|
|
|
// Click on a category filter
|
|
const filterButton = page.getByTestId('category-filter-all');
|
|
await filterButton.click();
|
|
|
|
// Wait for filter to apply
|
|
await page.waitForTimeout(1000);
|
|
|
|
// Verify league cards are still visible after filtering
|
|
const leagueCards = page.getByTestId('league-card');
|
|
await expect(leagueCards.first()).toBeVisible();
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
});
|
|
});
|
|
|
|
test.describe('2. /leagues/[id] (Overview Page)', () => {
|
|
test('Unauthenticated user can view league overview', async ({ page }) => {
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
await page.goto(leagueId, { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Verify page loads successfully
|
|
expect(page.url()).toContain('/leagues/');
|
|
|
|
// Verify league name is displayed
|
|
await expect(page.getByTestId('league-detail-title')).toBeVisible();
|
|
|
|
// Verify stats section displays
|
|
await expect(page.getByTestId('league-stats-section')).toBeVisible();
|
|
|
|
// Verify Next Race countdown displays correctly
|
|
await expect(page.getByTestId('next-race-countdown')).toBeVisible();
|
|
|
|
// Verify Season progress bar shows correct percentage
|
|
await expect(page.getByTestId('season-progress-bar')).toBeVisible();
|
|
|
|
// Verify Activity feed shows recent activity
|
|
await expect(page.getByTestId('activity-feed')).toBeVisible();
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
});
|
|
|
|
test('Authenticated user can view league overview', async ({ browser, request }) => {
|
|
const { context, page } = await WebsiteAuthManager.createAuthContext(browser, request, 'auth');
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
try {
|
|
await page.goto(leagueId, { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Verify page loads successfully
|
|
expect(page.url()).toContain('/leagues/');
|
|
|
|
// Verify league name is displayed
|
|
await expect(page.getByTestId('league-detail-title')).toBeVisible();
|
|
|
|
// Verify stats section displays
|
|
await expect(page.getByTestId('league-stats-section')).toBeVisible();
|
|
|
|
// Verify Next Race countdown displays correctly
|
|
await expect(page.getByTestId('next-race-countdown')).toBeVisible();
|
|
|
|
// Verify Season progress bar shows correct percentage
|
|
await expect(page.getByTestId('season-progress-bar')).toBeVisible();
|
|
|
|
// Verify Activity feed shows recent activity
|
|
await expect(page.getByTestId('activity-feed')).toBeVisible();
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
} finally {
|
|
await context.close();
|
|
}
|
|
});
|
|
|
|
test('Admin user can view admin widgets', async ({ browser, request }) => {
|
|
const { context, page } = await WebsiteAuthManager.createAuthContext(browser, request, 'admin');
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
try {
|
|
await page.goto(leagueId, { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Verify page loads successfully
|
|
expect(page.url()).toContain('/leagues/');
|
|
|
|
// Verify admin widgets are visible for authorized users
|
|
await expect(page.getByTestId('admin-widgets')).toBeVisible();
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
} finally {
|
|
await context.close();
|
|
}
|
|
});
|
|
|
|
test('Stats match API values', async ({ page, request }) => {
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
// Fetch API data
|
|
const apiResponse = await request.get(`${process.env.API_BASE_URL || 'http://api:3000'}/leagues/${WebsiteRouteManager.IDs.LEAGUE}`);
|
|
const apiData = await apiResponse.json();
|
|
|
|
// Navigate to league overview
|
|
await page.goto(leagueId, { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Verify stats match API values
|
|
const membersStat = page.getByTestId('stat-members');
|
|
const racesStat = page.getByTestId('stat-races');
|
|
const avgSofStat = page.getByTestId('stat-avg-sof');
|
|
|
|
await expect(membersStat).toBeVisible();
|
|
await expect(racesStat).toBeVisible();
|
|
await expect(avgSofStat).toBeVisible();
|
|
|
|
// Verify the stats contain expected values from API
|
|
const membersText = await membersStat.textContent();
|
|
const racesText = await racesStat.textContent();
|
|
const avgSofText = await avgSofStat.textContent();
|
|
|
|
// Basic validation - stats should not be empty
|
|
expect(membersText).toBeTruthy();
|
|
expect(racesText).toBeTruthy();
|
|
expect(avgSofText).toBeTruthy();
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
});
|
|
});
|
|
|
|
test.describe('3. /leagues/[id]/schedule (Schedule Page)', () => {
|
|
const schedulePath = routeManager.resolvePathTemplate('/leagues/[id]/schedule', { id: WebsiteRouteManager.IDs.LEAGUE });
|
|
|
|
test('Unauthenticated user can view schedule page', async ({ page }) => {
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
await page.goto(schedulePath, { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Verify page loads successfully
|
|
expect(page.url()).toContain('/schedule');
|
|
|
|
// Verify races are grouped by month
|
|
await expect(page.getByTestId('schedule-month-group')).toBeVisible();
|
|
|
|
// Verify race list is present
|
|
const raceItems = page.getByTestId('race-item');
|
|
await expect(raceItems.first()).toBeVisible();
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
});
|
|
|
|
test('Authenticated user can view schedule page', async ({ browser, request }) => {
|
|
const { context, page } = await WebsiteAuthManager.createAuthContext(browser, request, 'auth');
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
try {
|
|
await page.goto(schedulePath, { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Verify page loads successfully
|
|
expect(page.url()).toContain('/schedule');
|
|
|
|
// Verify races are grouped by month
|
|
await expect(page.getByTestId('schedule-month-group')).toBeVisible();
|
|
|
|
// Verify race list is present
|
|
const raceItems = page.getByTestId('race-item');
|
|
await expect(raceItems.first()).toBeVisible();
|
|
|
|
// Verify Register/Withdraw buttons are present
|
|
await expect(page.getByTestId('register-button')).toBeVisible();
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
} finally {
|
|
await context.close();
|
|
}
|
|
});
|
|
|
|
test('Admin user can view admin controls', async ({ browser, request }) => {
|
|
const { context, page } = await WebsiteAuthManager.createAuthContext(browser, request, 'admin');
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
try {
|
|
await page.goto(schedulePath, { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Verify page loads successfully
|
|
expect(page.url()).toContain('/schedule');
|
|
|
|
// Verify admin controls are visible for authorized users
|
|
await expect(page.getByTestId('admin-controls')).toBeVisible();
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
} finally {
|
|
await context.close();
|
|
}
|
|
});
|
|
|
|
test('Race detail modal shows correct data', async ({ page, request }) => {
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
// Fetch API data
|
|
const apiResponse = await request.get(`${process.env.API_BASE_URL || 'http://api:3000'}/leagues/${WebsiteRouteManager.IDs.LEAGUE}/schedule`);
|
|
const apiData = await apiResponse.json();
|
|
|
|
// Navigate to schedule page
|
|
await page.goto(schedulePath, { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Click on a race item to open modal
|
|
const raceItem = page.getByTestId('race-item').first();
|
|
await raceItem.click();
|
|
|
|
// Verify modal is visible
|
|
await expect(page.getByTestId('race-detail-modal')).toBeVisible();
|
|
|
|
// Verify modal contains race data
|
|
const modalContent = page.getByTestId('race-detail-modal');
|
|
await expect(modalContent.getByTestId('race-track')).toBeVisible();
|
|
await expect(modalContent.getByTestId('race-car')).toBeVisible();
|
|
await expect(modalContent.getByTestId('race-date')).toBeVisible();
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
});
|
|
});
|
|
|
|
test.describe('4. /leagues/[id]/standings (Standings Page)', () => {
|
|
const standingsPath = routeManager.resolvePathTemplate('/leagues/[id]/standings', { id: WebsiteRouteManager.IDs.LEAGUE });
|
|
|
|
test('Unauthenticated user can view standings page', async ({ page }) => {
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
await page.goto(standingsPath, { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Verify page loads successfully
|
|
expect(page.url()).toContain('/standings');
|
|
|
|
// Verify standings table is present
|
|
await expect(page.getByTestId('standings-table')).toBeVisible();
|
|
|
|
// Verify trend indicators display correctly
|
|
await expect(page.getByTestId('trend-indicator')).toBeVisible();
|
|
|
|
// Verify championship stats show correct data
|
|
await expect(page.getByTestId('championship-stats')).toBeVisible();
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
});
|
|
|
|
test('Authenticated user can view standings page', async ({ browser, request }) => {
|
|
const { context, page } = await WebsiteAuthManager.createAuthContext(browser, request, 'auth');
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
try {
|
|
await page.goto(standingsPath, { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Verify page loads successfully
|
|
expect(page.url()).toContain('/standings');
|
|
|
|
// Verify standings table is present
|
|
await expect(page.getByTestId('standings-table')).toBeVisible();
|
|
|
|
// Verify trend indicators display correctly
|
|
await expect(page.getByTestId('trend-indicator')).toBeVisible();
|
|
|
|
// Verify championship stats show correct data
|
|
await expect(page.getByTestId('championship-stats')).toBeVisible();
|
|
|
|
// Verify team standings toggle is present
|
|
await expect(page.getByTestId('team-standings-toggle')).toBeVisible();
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
} finally {
|
|
await context.close();
|
|
}
|
|
});
|
|
|
|
test('Team standings toggle works correctly', async ({ page }) => {
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
await page.goto(standingsPath, { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Verify team standings toggle is present
|
|
await expect(page.getByTestId('team-standings-toggle')).toBeVisible();
|
|
|
|
// Click on team standings toggle
|
|
const toggle = page.getByTestId('team-standings-toggle');
|
|
await toggle.click();
|
|
|
|
// Wait for toggle to apply
|
|
await page.waitForTimeout(1000);
|
|
|
|
// Verify team standings are visible
|
|
await expect(page.getByTestId('team-standings-table')).toBeVisible();
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
});
|
|
|
|
test('Drop weeks are marked correctly', async ({ page }) => {
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
await page.goto(standingsPath, { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Verify drop weeks are marked
|
|
const dropWeeks = page.getByTestId('drop-week-marker');
|
|
await expect(dropWeeks.first()).toBeVisible();
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
});
|
|
|
|
test('Standings data matches API values', async ({ page, request }) => {
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
// Fetch API data
|
|
const apiResponse = await request.get(`${process.env.API_BASE_URL || 'http://api:3000'}/leagues/${WebsiteRouteManager.IDs.LEAGUE}/standings`);
|
|
const apiData = await apiResponse.json();
|
|
|
|
// Navigate to standings page
|
|
await page.goto(standingsPath, { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Verify standings table is present
|
|
await expect(page.getByTestId('standings-table')).toBeVisible();
|
|
|
|
// Verify table rows match API data
|
|
const tableRows = page.getByTestId('standings-row');
|
|
const rowCount = await tableRows.count();
|
|
|
|
// Basic validation - should have at least one row
|
|
expect(rowCount).toBeGreaterThan(0);
|
|
|
|
// Verify first row contains expected data
|
|
const firstRow = tableRows.first();
|
|
await expect(firstRow.getByTestId('standing-position')).toBeVisible();
|
|
await expect(firstRow.getByTestId('standing-driver')).toBeVisible();
|
|
await expect(firstRow.getByTestId('standing-points')).toBeVisible();
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
});
|
|
});
|
|
|
|
test.describe('5. /leagues/[id]/roster (Roster Page)', () => {
|
|
const rosterPath = routeManager.resolvePathTemplate('/leagues/[id]/roster', { id: WebsiteRouteManager.IDs.LEAGUE });
|
|
|
|
test('Unauthenticated user can view roster page', async ({ page }) => {
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
await page.goto(rosterPath, { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Verify page loads successfully
|
|
expect(page.url()).toContain('/roster');
|
|
|
|
// Verify driver cards are present
|
|
const driverCards = page.getByTestId('driver-card');
|
|
await expect(driverCards.first()).toBeVisible();
|
|
|
|
// Verify driver cards show correct stats
|
|
const firstCard = driverCards.first();
|
|
await expect(firstCard.getByTestId('driver-card-name')).toBeVisible();
|
|
await expect(firstCard.getByTestId('driver-card-stats')).toBeVisible();
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
});
|
|
|
|
test('Authenticated user can view roster page', async ({ browser, request }) => {
|
|
const { context, page } = await WebsiteAuthManager.createAuthContext(browser, request, 'auth');
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
try {
|
|
await page.goto(rosterPath, { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Verify page loads successfully
|
|
expect(page.url()).toContain('/roster');
|
|
|
|
// Verify driver cards are present
|
|
const driverCards = page.getByTestId('driver-card');
|
|
await expect(driverCards.first()).toBeVisible();
|
|
|
|
// Verify driver cards show correct stats
|
|
const firstCard = driverCards.first();
|
|
await expect(firstCard.getByTestId('driver-card-name')).toBeVisible();
|
|
await expect(firstCard.getByTestId('driver-card-stats')).toBeVisible();
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
} finally {
|
|
await context.close();
|
|
}
|
|
});
|
|
|
|
test('Admin user can view admin actions', async ({ browser, request }) => {
|
|
const { context, page } = await WebsiteAuthManager.createAuthContext(browser, request, 'admin');
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
try {
|
|
await page.goto(rosterPath, { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Verify page loads successfully
|
|
expect(page.url()).toContain('/roster');
|
|
|
|
// Verify admin actions are visible for authorized users
|
|
await expect(page.getByTestId('admin-actions')).toBeVisible();
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
} finally {
|
|
await context.close();
|
|
}
|
|
});
|
|
|
|
test('Roster data matches API values', async ({ page, request }) => {
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
// Fetch API data
|
|
const apiResponse = await request.get(`${process.env.API_BASE_URL || 'http://api:3000'}/leagues/${WebsiteRouteManager.IDs.LEAGUE}/memberships`);
|
|
const apiData = await apiResponse.json();
|
|
|
|
// Navigate to roster page
|
|
await page.goto(rosterPath, { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Verify driver cards are present
|
|
const driverCards = page.getByTestId('driver-card');
|
|
const cardCount = await driverCards.count();
|
|
|
|
// Basic validation - should have at least one driver
|
|
expect(cardCount).toBeGreaterThan(0);
|
|
|
|
// Verify first card contains expected data
|
|
const firstCard = driverCards.first();
|
|
await expect(firstCard.getByTestId('driver-card-name')).toBeVisible();
|
|
await expect(firstCard.getByTestId('driver-card-stats')).toBeVisible();
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
});
|
|
});
|
|
|
|
test.describe('6. Navigation Between League Pages', () => {
|
|
test('User can navigate from discovery to league overview', async ({ page }) => {
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
// Navigate to leagues discovery page
|
|
await page.goto('/leagues', { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Click on a league card
|
|
const leagueCard = page.getByTestId('league-card').first();
|
|
await leagueCard.click();
|
|
|
|
// Verify navigation to league overview
|
|
await page.waitForURL(/\/leagues\/[^/]+$/, { timeout: 15000 });
|
|
expect(page.url()).toMatch(/\/leagues\/[^/]+$/);
|
|
|
|
// Verify league overview content is visible
|
|
await expect(page.getByTestId('league-detail-title')).toBeVisible();
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
});
|
|
|
|
test('User can navigate between league sub-pages', async ({ page }) => {
|
|
const capture = new ConsoleErrorCapture(page);
|
|
capture.setAllowlist(CONSOLE_ALLOWLIST);
|
|
|
|
// Navigate to league overview
|
|
await page.goto(leagueId, { waitUntil: 'commit', timeout: 15000 });
|
|
|
|
// Click on Schedule tab
|
|
const scheduleTab = page.getByTestId('schedule-tab');
|
|
await scheduleTab.click();
|
|
|
|
// Verify navigation to schedule page
|
|
await page.waitForURL(/\/leagues\/[^/]+\/schedule$/, { timeout: 15000 });
|
|
expect(page.url()).toMatch(/\/leagues\/[^/]+\/schedule$/);
|
|
|
|
// Click on Standings tab
|
|
const standingsTab = page.getByTestId('standings-tab');
|
|
await standingsTab.click();
|
|
|
|
// Verify navigation to standings page
|
|
await page.waitForURL(/\/leagues\/[^/]+\/standings$/, { timeout: 15000 });
|
|
expect(page.url()).toMatch(/\/leagues\/[^/]+\/standings$/);
|
|
|
|
// Click on Roster tab
|
|
const rosterTab = page.getByTestId('roster-tab');
|
|
await rosterTab.click();
|
|
|
|
// Verify navigation to roster page
|
|
await page.waitForURL(/\/leagues\/[^/]+\/roster$/, { timeout: 15000 });
|
|
expect(page.url()).toMatch(/\/leagues\/[^/]+\/roster$/);
|
|
|
|
expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
|
|
});
|
|
});
|
|
});
|