58857af5ca
- Add password-reset.feature with 4 scenarios - Add step definition for password reset page assertion - Tests access page, valid email request, invalid email, and empty field
304 lines
9.9 KiB
TypeScript
304 lines
9.9 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 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}`);
|
|
});
|