Files
Profa 2777ebab3d feat: Add comprehensive E2E test suite for Agile Testing Days 2025
Added complete Playwright-based end-to-end test suite for the Agile Testing Days 2025 conference website (https://agiletestingdays.com/). This test suite enables automated functional testing of critical user journeys including registration, payment processing, navigation, and form submissions.

Key components:
- Comprehensive test plan with 67 BDD scenarios covering navigation, registration, payment, newsletter, FAQ, Call for Papers, speakers, and external integrations
- 78+ Playwright test cases organized by priority (P0/P1/P2) with Page Object Model pattern
- Complete test infrastructure with fixtures, utilities, and test data factories
- Full documentation including setup guide, test execution instructions, and configuration examples
- Support for parallel execution, CI/CD integration, and multiple report formats

This test suite was created to validate the conference website functionality and can be shared with the Agile Testing Days team.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 13:18:02 +00:00

114 lines
3.2 KiB
TypeScript

import { Page, Locator } from '@playwright/test';
/**
* BasePage - Base class for all Page Objects
* Provides common functionality used across all pages
*/
export class BasePage {
readonly page: Page;
constructor(page: Page) {
this.page = page;
}
// Navigation
async goto(path: string = '/'): Promise<void> {
await this.page.goto(path);
}
async clickLogo(): Promise<void> {
await this.page.click('a[href="/"] img, .logo, header img');
}
// Common elements
getNavigationMenu(): Locator {
return this.page.locator('nav, .navigation, .main-menu, header ul');
}
async clickNavigationItem(itemText: string): Promise<void> {
const nav = this.getNavigationMenu();
await nav.locator(`text="${itemText}"`).first().click();
}
async waitForPageLoad(): Promise<void> {
await this.page.waitForLoadState('networkidle');
}
// Form helpers
async fillInput(selector: string, value: string): Promise<void> {
await this.page.fill(selector, value);
}
async selectDropdown(selector: string, value: string): Promise<void> {
await this.page.selectOption(selector, value);
}
async clickButton(text: string): Promise<void> {
await this.page.click(`button:has-text("${text}"), input[type="submit"][value*="${text}"]`);
}
async checkCheckbox(selector: string): Promise<void> {
await this.page.check(selector);
}
async uncheckCheckbox(selector: string): Promise<void> {
await this.page.uncheck(selector);
}
// Validation helpers
async getValidationError(fieldName: string): Promise<string | null> {
const errorSelectors = [
`[name="${fieldName}"] ~ .error, [name="${fieldName}"] ~ .error-message`,
`[name="${fieldName}"] + .error, [name="${fieldName}"] + .error-message`,
`.field-${fieldName} .error, .field-${fieldName} .error-message`,
`#${fieldName}-error, [data-error-for="${fieldName}"]`,
];
for (const selector of errorSelectors) {
const errorElement = this.page.locator(selector).first();
if (await errorElement.isVisible({ timeout: 2000 }).catch(() => false)) {
return await errorElement.textContent();
}
}
return null;
}
async hasValidationError(): Promise<boolean> {
const errorElements = this.page.locator('.error, .error-message, [class*="error"]');
return await errorElements.count() > 0;
}
// URL helpers
async getCurrentUrl(): Promise<string> {
return this.page.url();
}
async waitForUrl(pattern: string | RegExp): Promise<void> {
await this.page.waitForURL(pattern);
}
// Content helpers
async getPageTitle(): Promise<string> {
return await this.page.title();
}
async hasText(text: string): Promise<boolean> {
return await this.page.locator(`text=${text}`).isVisible();
}
// External links
async clickExternalLink(linkText: string): Promise<Page> {
const [newPage] = await Promise.all([
this.page.context().waitForEvent('page'),
this.page.click(`a:has-text("${linkText}")`),
]);
await newPage.waitForLoadState();
return newPage;
}
// Screenshot helper
async takeScreenshot(name: string): Promise<void> {
await this.page.screenshot({ path: `test-results/screenshots/${name}.png`, fullPage: true });
}
}