Files
euchre_camp/e2e/cucumber/step-definitions/common-steps.ts
T
david a0909c82a0 feat: add tournament schedule feature test (issue #7)
- Add tournament-schedule.feature with 4 scenarios
- Add step definitions for tournament schedule navigation
- Tests viewing schedule, generating round-robin, bye rounds, and matchup navigation
- Note: Some @wip scenarios require data setup (tournament creation, team addition)
2026-04-26 04:25:56 +00:00

310 lines
10 KiB
TypeScript

/**
* Common step definitions for EuchreCamp E2E tests
*/
import { Given, When, Then } from '@cucumber/cucumber';
import { expect } from '@playwright/test';
import { world } from '../support/world';
// console.log('🌍 Loading common-steps.ts step definitions');
/**
* Navigation steps
*/
Given('I am on the home page', async function () {
console.log('🌍 Navigating to home page');
await world.page.goto(world.baseURL);
await world.page.waitForLoadState('networkidle');
});
Given('I am on the registration page', async function () {
console.log('🌍 Navigating to registration page');
await world.page.goto(`${world.baseURL}/auth/register`);
await world.page.waitForLoadState('networkidle');
});
Given('I am on the login page', async function () {
console.log('🌍 Navigating to login page');
await world.page.goto(`${world.baseURL}/auth/login`);
await world.page.waitForLoadState('networkidle');
});
Given('I am on the {string} page', async function (pageName: string) {
const pageUrls: Record<string, string> = {
'home': '/',
'home page': '/',
'registration': '/auth/register',
'registration page': '/auth/register',
'login': '/auth/login',
'login page': '/auth/login',
'rankings': '/rankings',
'rankings page': '/rankings',
'admin': '/admin',
'admin page': '/admin',
'admin dashboard': '/admin',
'tournaments': '/admin/tournaments',
'tournaments page': '/admin/tournaments',
};
const url = pageUrls[pageName.toLowerCase()] || `/${pageName.toLowerCase().replace(' ', '-')}`;
console.log(`🌍 Navigating to ${pageName}: ${url}`);
await world.page.goto(`${world.baseURL}${url}`);
// Wait for page to load
await world.page.waitForLoadState('networkidle');
});
When('I navigate to the {string} page', async function (pageName: string) {
// This step is a synonym for "I go to the {string} page"
await world.page.goto(`${world.baseURL}/auth/register`);
await world.page.waitForLoadState('networkidle');
});
When('I navigate to the registration page', async function () {
console.log('🌍 Navigating to registration page');
await world.page.goto(`${world.baseURL}/auth/register`);
await world.page.waitForLoadState('networkidle');
});
When('I go to the home page', async function () {
console.log('🌍 Navigating to home page');
await world.page.goto(world.baseURL);
await world.page.waitForLoadState('networkidle');
});
When('I go to the {string} page', async function (pageName: string) {
const pageUrls: Record<string, string> = {
'home': '/',
'home page': '/',
'registration': '/auth/register',
'registration page': '/auth/register',
'login': '/auth/login',
'login page': '/auth/login',
'rankings': '/rankings',
'rankings page': '/rankings',
'admin': '/admin',
'admin page': '/admin',
'admin dashboard': '/admin',
'tournaments': '/admin/tournaments',
'tournaments page': '/admin/tournaments',
};
const url = pageUrls[pageName.toLowerCase()] || `/${pageName.toLowerCase().replace(' ', '-')}`;
console.log(`🌍 Going to ${pageName}: ${url}`);
await world.page.goto(`${world.baseURL}${url}`);
await world.page.waitForLoadState('networkidle');
});
When('I go back', async function () {
await world.page.goBack();
await world.page.waitForLoadState('networkidle');
});
When('I refresh the page', async function () {
await world.page.reload();
await world.page.waitForLoadState('networkidle');
});
/**
* Form interaction steps
*/
When('I fill in {string} with {string}', async function (fieldName: string, value: string) {
// Map field names to selectors
const fieldSelectors: Record<string, string> = {
'name': 'input[name="name"]',
'email': 'input[name="email"]',
'password': 'input[name="password"]',
'confirm password': 'input[name="confirmPassword"]',
'player name': 'input[name="playerName"]',
'tournament name': 'input[name="name"]',
};
const selector = fieldSelectors[fieldName.toLowerCase()] || `input[name="${fieldName.toLowerCase()}"]`;
console.log(`🌍 Filling ${fieldName} with ${value}`);
await world.page.fill(selector, value);
});
When('I click the {string} button', async function (buttonText: string) {
const selector = `button:has-text("${buttonText}")`;
console.log(`🌍 Clicking button: ${buttonText}`);
await world.page.click(selector);
});
When('I click the {string} link', async function (linkText: string) {
const selector = `a:has-text("${linkText}")`;
console.log(`🌍 Clicking link: ${linkText}`);
await world.page.click(selector);
});
When('I click the {string} wordmark', async function (wordmarkText: string) {
const selector = `a:has-text("${wordmarkText}")`;
console.log(`🌍 Clicking wordmark: ${wordmarkText}`);
await world.page.click(selector);
await world.page.waitForLoadState('networkidle');
});
When('I click the {string} element', async function (elementText: string) {
const selector = `text=${elementText}`;
console.log(`🌍 Clicking element: ${elementText}`);
await world.page.click(selector);
});
/**
* Assertion steps
*/
Then('I should see {string}', async function (text: string) {
console.log(`🌍 Checking for text: ${text}`);
await expect(world.page.locator(`text=${text}`)).toBeVisible();
});
Then('I should not see {string}', async function (text: string) {
console.log(`🌍 Checking text is NOT visible: ${text}`);
await expect(world.page.locator(`text=${text}`)).not.toBeVisible();
});
Then('I should be on the {string} page', async function (pageName: string) {
const pageUrls: Record<string, string> = {
'home': '/',
'home page': '/',
'registration': '/auth/register',
'registration page': '/auth/register',
'login': '/auth/login',
'login page': '/auth/login',
'profile': '/players',
'admin': '/admin',
'admin page': '/admin',
};
const expectedPath = pageUrls[pageName.toLowerCase()] || `/${pageName.toLowerCase().replace(' ', '-')}`;
const currentUrl = world.page.url();
console.log(`🌍 Checking current URL: ${currentUrl}`);
console.log(`🌍 Expected path: ${expectedPath}`);
expect(currentUrl).toContain(expectedPath);
});
Then('I should be redirected to my profile page', async function () {
await world.page.waitForLoadState('networkidle');
const currentUrl = world.page.url();
console.log(`🌍 Checking redirect to profile page. Current URL: ${currentUrl}`);
expect(currentUrl).toMatch(/\/players\/\d+\/profile/);
});
Then('I should be on the registration page', async function () {
const currentUrl = world.page.url();
console.log(`🌍 Checking current URL: ${currentUrl}`);
expect(currentUrl).toContain('/auth/register');
});
Then('I should be on the login page', async function () {
const currentUrl = world.page.url();
console.log(`🌍 Checking current URL: ${currentUrl}`);
expect(currentUrl).toContain('/auth/login');
});
Then('I should be on the admin page', async function () {
const currentUrl = world.page.url();
console.log(`🌍 Checking current URL: ${currentUrl}`);
expect(currentUrl).toContain('/admin');
});
Then('I should be on the home page', async function () {
const currentUrl = world.page.url();
console.log(`🌍 Checking current URL: ${currentUrl}`);
expect(currentUrl).toContain('/');
});
Then('I should be on the password reset page', async function () {
const currentUrl = world.page.url();
console.log(`🌍 Checking current URL: ${currentUrl}`);
expect(currentUrl).toContain('/auth/password-reset');
});
Then('I should see the {string} button', async function (buttonText: string) {
const button = world.page.locator(`button:has-text("${buttonText}")`);
await expect(button).toBeVisible();
console.log(`🌍 Verified button is visible: ${buttonText}`);
});
Then('I should be redirected to {string}', async function (path: string) {
await world.page.waitForLoadState('networkidle');
const currentUrl = world.page.url();
console.log(`🌍 Checking redirect to: ${path}`);
console.log(`🌍 Current URL: ${currentUrl}`);
expect(currentUrl).toContain(path);
});
/**
* Element visibility steps
*/
Then('the element {string} should be visible', async function (elementText: string) {
const element = world.page.locator(`text=${elementText}`);
await expect(element).toBeVisible();
});
Then('the element {string} should not be visible', async function (elementText: string) {
const element = world.page.locator(`text=${elementText}`);
await expect(element).not.toBeVisible();
});
/**
* Wait steps
*/
When('I wait for {int} seconds', async function (seconds: number) {
console.log(`🌍 Waiting ${seconds} seconds`);
await world.page.waitForTimeout(seconds * 1000);
});
When('I wait for the page to load', async function () {
await world.page.waitForLoadState('networkidle');
});
/**
* URL verification steps
*/
Then('the URL should contain {string}', async function (expectedPath: string) {
const currentUrl = world.page.url();
console.log(`🌍 Checking URL contains: ${expectedPath}`);
expect(currentUrl).toContain(expectedPath);
});
Then('I should be redirected to the login page', async function () {
await world.page.waitForLoadState('networkidle');
const currentUrl = world.page.url();
console.log(`🌍 Checking redirect to login page. Current URL: ${currentUrl}`);
expect(currentUrl).toContain('/auth/login');
});
Then('I should see a {string} error', async function (errorMessage: string) {
const content = await world.page.content();
expect(content).toMatch(new RegExp(errorMessage, 'i'));
console.log(`🌍 Verified error message: ${errorMessage}`);
});
Then('I should see {string} validation error', async function (field: string) {
// Look for validation error near the input field
const content = await world.page.content();
// Check if the field name is mentioned in an error context
expect(content).toMatch(new RegExp(field, 'i'));
console.log(`🌍 Verified validation error for: ${field}`);
});
Then('I should see {string} error', async function (errorMessage: string) {
const content = await world.page.content();
expect(content).toMatch(new RegExp(errorMessage, 'i'));
console.log(`🌍 Verified error message: ${errorMessage}`);
});