Initialize fork and rebrand app to event_manager
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
import { expect, Locator, Page } from "@playwright/test";
|
||||
|
||||
export class BookingPage {
|
||||
private page: Page;
|
||||
attendeeNameInput: Locator;
|
||||
attendeeEmailInput: Locator;
|
||||
ticketTypeSelect: Locator;
|
||||
addOnCheckboxes: Locator;
|
||||
private bookButton: Locator;
|
||||
private addAttendeeButton: Locator;
|
||||
private bookingForm: Locator;
|
||||
private summarySection: Locator;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
|
||||
// Form elements
|
||||
this.attendeeNameInput = page
|
||||
.locator('input[placeholder*="name" i], input[name*="name" i]')
|
||||
.first();
|
||||
this.attendeeEmailInput = page
|
||||
.locator('input[type="email"], input[placeholder*="email" i]')
|
||||
.first();
|
||||
this.ticketTypeSelect = page.locator('select, [data-testid="ticket-type"]').first();
|
||||
|
||||
// Add-ons
|
||||
this.addOnCheckboxes = page.locator('input[type="checkbox"]');
|
||||
|
||||
// Buttons
|
||||
this.bookButton = page.locator('button[type="submit"]');
|
||||
this.addAttendeeButton = page.locator('button:has-text("Add Another Attendee")');
|
||||
|
||||
// Sections
|
||||
this.bookingForm = page.locator("form");
|
||||
this.summarySection = page.locator('[class*="summary" i]').first();
|
||||
}
|
||||
|
||||
// Navigate to the booking page for a specific event.
|
||||
async goto(eventRoute: string): Promise<void> {
|
||||
await this.page.goto(`/dashboard/book-tickets/${eventRoute}`);
|
||||
await this.page.waitForLoadState("networkidle");
|
||||
}
|
||||
|
||||
// Wait for the booking form to fully load.
|
||||
async waitForFormLoad(): Promise<void> {
|
||||
await expect(this.bookingForm).toBeVisible({ timeout: 15000 });
|
||||
}
|
||||
|
||||
// Fill in attendee details.
|
||||
async fillAttendeeDetails(name: string, email: string): Promise<void> {
|
||||
await this.attendeeNameInput.fill(name);
|
||||
await this.attendeeEmailInput.fill(email);
|
||||
}
|
||||
|
||||
// Select a ticket type by its visible text.
|
||||
async selectTicketType(ticketTitle: string): Promise<void> {
|
||||
const ticketOption = this.page.locator(`text=${ticketTitle}`).first();
|
||||
if (await ticketOption.isVisible()) {
|
||||
await ticketOption.click();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle an add-on by its title.
|
||||
*/
|
||||
async toggleAddOn(addOnTitle: string): Promise<void> {
|
||||
const addOnLabel = this.page.locator(`label:has-text("${addOnTitle}")`).first();
|
||||
if (await addOnLabel.isVisible()) {
|
||||
await addOnLabel.click();
|
||||
}
|
||||
}
|
||||
|
||||
// Add another attendee to the booking.
|
||||
async addAnotherAttendee(): Promise<void> {
|
||||
await this.addAttendeeButton.click();
|
||||
}
|
||||
|
||||
// Submit the booking form.
|
||||
async submit(): Promise<void> {
|
||||
await this.bookButton.click();
|
||||
}
|
||||
|
||||
// Get the booking button text.
|
||||
async getBookButtonText(): Promise<string | null> {
|
||||
return this.bookButton.textContent();
|
||||
}
|
||||
|
||||
// Assert that the booking form is visible.
|
||||
async expectFormVisible(): Promise<void> {
|
||||
await expect(this.bookingForm).toBeVisible();
|
||||
}
|
||||
|
||||
// Assert that ticket types are displayed.
|
||||
async expectTicketTypesVisible(): Promise<void> {
|
||||
// Check for any ticket-related content
|
||||
const ticketContent = this.page
|
||||
.locator('[class*="ticket"], select, input[type="radio"]')
|
||||
.first();
|
||||
await expect(ticketContent).toBeVisible({ timeout: 10000 });
|
||||
}
|
||||
|
||||
// Assert that add-ons are displayed.
|
||||
async expectAddOnsVisible(): Promise<void> {
|
||||
const addOnCount = await this.addOnCheckboxes.count();
|
||||
expect(addOnCount).toBeGreaterThan(0);
|
||||
}
|
||||
|
||||
// Assert that the book button is visible with expected text.
|
||||
async expectBookButtonVisible(): Promise<void> {
|
||||
await expect(this.bookButton).toBeVisible();
|
||||
const text = await this.bookButton.textContent();
|
||||
expect(text?.match(/Book|Pay|Register/i)).toBeTruthy();
|
||||
}
|
||||
|
||||
// Get the count of attendee forms on the page.
|
||||
async getAttendeeCount(): Promise<number> {
|
||||
const attendeeForms = this.page.locator('[class*="attendee"], [class*="Attendee"]');
|
||||
return await attendeeForms.count();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
import { expect, Locator, Page } from "@playwright/test";
|
||||
|
||||
export class CustomFormPage {
|
||||
private page: Page;
|
||||
private form: Locator;
|
||||
private submitButton: Locator;
|
||||
private successBanner: Locator;
|
||||
private closedBanner: Locator;
|
||||
private errorBanner: Locator;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
this.form = page.locator("form");
|
||||
this.submitButton = page.locator('button[type="submit"]').filter({ hasText: /^Submit$/ });
|
||||
this.successBanner = page.locator(".bg-surface-green-1");
|
||||
this.closedBanner = page.locator(".bg-surface-orange-1");
|
||||
this.errorBanner = page.locator(".bg-surface-amber-1");
|
||||
}
|
||||
|
||||
async goto(eventRoute: string, formRoute: string): Promise<void> {
|
||||
await this.page.goto(`/dashboard/events/${eventRoute}/forms/${formRoute}`);
|
||||
await this.page.waitForLoadState("networkidle");
|
||||
}
|
||||
|
||||
async waitForFormLoad(): Promise<void> {
|
||||
await expect(this.form).toBeVisible({ timeout: 15000 });
|
||||
}
|
||||
|
||||
getInputByLabel(label: string): Locator {
|
||||
return this.page
|
||||
.locator(`label:has-text("${label}")`)
|
||||
.locator("..")
|
||||
.locator("input, textarea, select")
|
||||
.first();
|
||||
}
|
||||
|
||||
async submit(): Promise<void> {
|
||||
await this.submitButton.click();
|
||||
}
|
||||
|
||||
async expectFormVisible(): Promise<void> {
|
||||
await expect(this.form).toBeVisible();
|
||||
}
|
||||
|
||||
async expectFormTitle(title: string): Promise<void> {
|
||||
await expect(this.page.locator(`h1:has-text("${title}")`)).toBeVisible();
|
||||
}
|
||||
|
||||
async expectFieldVisible(label: string): Promise<void> {
|
||||
await expect(this.page.locator(`label:has-text("${label}")`)).toBeVisible();
|
||||
}
|
||||
|
||||
async expectSubmitButtonVisible(): Promise<void> {
|
||||
await expect(this.submitButton).toBeVisible();
|
||||
const text = await this.submitButton.textContent();
|
||||
expect(text?.match(/Submit/i)).toBeTruthy();
|
||||
}
|
||||
|
||||
async submitAndExpectResponse(): Promise<{ succeeded: boolean; status: number }> {
|
||||
const responsePromise = this.page.waitForResponse(
|
||||
(resp) => resp.url().includes("submit_custom_form"),
|
||||
{ timeout: 20000 },
|
||||
);
|
||||
|
||||
await this.submitButton.click();
|
||||
|
||||
const response = await responsePromise;
|
||||
const status = response.status();
|
||||
const succeeded = status === 200;
|
||||
|
||||
if (succeeded) {
|
||||
await expect(this.successBanner).toBeVisible({ timeout: 15000 });
|
||||
} else {
|
||||
await expect(this.form).toBeVisible();
|
||||
}
|
||||
|
||||
return { succeeded, status };
|
||||
}
|
||||
|
||||
async expectSuccess(): Promise<void> {
|
||||
await expect(this.successBanner).toBeVisible({ timeout: 15000 });
|
||||
}
|
||||
|
||||
async expectClosed(): Promise<void> {
|
||||
await expect(this.closedBanner).toBeVisible({ timeout: 15000 });
|
||||
}
|
||||
|
||||
async expectNotFound(): Promise<void> {
|
||||
await expect(this.errorBanner).toBeVisible({ timeout: 15000 });
|
||||
}
|
||||
|
||||
async getFieldLabels(): Promise<string[]> {
|
||||
const labels = this.page.locator("form label");
|
||||
return labels.allTextContents();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import { expect, Locator, Page } from "@playwright/test";
|
||||
|
||||
export class EventProposalPage {
|
||||
private page: Page;
|
||||
private form: Locator;
|
||||
private submitButton: Locator;
|
||||
private successBanner: Locator;
|
||||
private notFoundBanner: Locator;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
this.form = page.locator("form");
|
||||
this.submitButton = page.locator('button[type="submit"]').filter({ hasText: /^Submit$/ });
|
||||
this.successBanner = page.locator(".bg-surface-green-1");
|
||||
this.notFoundBanner = page.locator(".bg-surface-amber-1");
|
||||
}
|
||||
|
||||
async goto(): Promise<void> {
|
||||
await this.page.goto("/dashboard/event-proposal");
|
||||
await this.page.waitForLoadState("networkidle");
|
||||
}
|
||||
|
||||
async waitForFormLoad(): Promise<void> {
|
||||
await expect(this.form).toBeVisible({ timeout: 15000 });
|
||||
}
|
||||
|
||||
getInputByLabel(label: string): Locator {
|
||||
return this.page
|
||||
.locator(`label:has-text("${label}")`)
|
||||
.locator("..")
|
||||
.locator("input, textarea, select")
|
||||
.first();
|
||||
}
|
||||
|
||||
async expectFormVisible(): Promise<void> {
|
||||
await expect(this.form).toBeVisible();
|
||||
}
|
||||
|
||||
async expectBannerTitle(title: string): Promise<void> {
|
||||
await expect(this.page.locator(`h1:has-text("${title}")`)).toBeVisible();
|
||||
}
|
||||
|
||||
async expectFieldVisible(label: string): Promise<void> {
|
||||
await expect(this.page.locator(`label:has-text("${label}")`)).toBeVisible();
|
||||
}
|
||||
|
||||
async expectSubmitButtonVisible(): Promise<void> {
|
||||
await expect(this.submitButton).toBeVisible();
|
||||
}
|
||||
|
||||
async expectSuccess(): Promise<void> {
|
||||
await expect(this.successBanner).toBeVisible({ timeout: 15000 });
|
||||
}
|
||||
|
||||
async expectNotFound(): Promise<void> {
|
||||
await expect(this.notFoundBanner).toBeVisible({ timeout: 15000 });
|
||||
}
|
||||
|
||||
async submit(): Promise<void> {
|
||||
await this.submitButton.click();
|
||||
}
|
||||
|
||||
async submitAndExpectResponse(): Promise<{ succeeded: boolean; status: number }> {
|
||||
const responsePromise = this.page.waitForResponse(
|
||||
(resp) => resp.url().includes("submit_event_proposal"),
|
||||
{ timeout: 20000 },
|
||||
);
|
||||
|
||||
await this.submitButton.click();
|
||||
|
||||
const response = await responsePromise;
|
||||
const status = response.status();
|
||||
const succeeded = status === 200;
|
||||
|
||||
if (succeeded) {
|
||||
await expect(this.successBanner).toBeVisible({ timeout: 15000 });
|
||||
}
|
||||
|
||||
return { succeeded, status };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export { LoginPage } from "./login.page";
|
||||
export { BookingPage } from "./booking.page";
|
||||
export { CustomFormPage } from "./custom-form.page";
|
||||
export { EventProposalPage } from "./event-proposal.page";
|
||||
@@ -0,0 +1,69 @@
|
||||
import { expect, Locator, Page } from "@playwright/test";
|
||||
|
||||
/**
|
||||
* Page Object for the Frappe login page.
|
||||
*/
|
||||
export class LoginPage {
|
||||
private page: Page;
|
||||
private emailInput: Locator;
|
||||
private passwordInput: Locator;
|
||||
private submitButton: Locator;
|
||||
private errorMessage: Locator;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
|
||||
// Frappe login page selectors
|
||||
this.emailInput = page.locator("#login_email");
|
||||
this.passwordInput = page.locator("#login_password");
|
||||
this.submitButton = page.locator("button.btn-login");
|
||||
this.errorMessage = page.locator(".msgprint, .alert-danger").first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigate to the login page.
|
||||
*/
|
||||
async goto(): Promise<void> {
|
||||
await this.page.goto("/login");
|
||||
await this.page.waitForLoadState("networkidle");
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill in the login form with credentials.
|
||||
*/
|
||||
async fillCredentials(email: string, password: string): Promise<void> {
|
||||
await this.emailInput.fill(email);
|
||||
await this.passwordInput.fill(password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit the login form.
|
||||
*/
|
||||
async submit(): Promise<void> {
|
||||
await this.submitButton.click();
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a complete login.
|
||||
*/
|
||||
async login(email = "Administrator", password = "admin"): Promise<void> {
|
||||
await this.goto();
|
||||
await this.fillCredentials(email, password);
|
||||
await this.submit();
|
||||
await this.page.waitForURL(/\/(app|desk|event_manager)/, { timeout: 30000 });
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that login failed with an error.
|
||||
*/
|
||||
async expectLoginError(): Promise<void> {
|
||||
await expect(this.errorMessage).toBeVisible();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that we're on the login page.
|
||||
*/
|
||||
async expectToBeOnLoginPage(): Promise<void> {
|
||||
await expect(this.page).toHaveURL(/.*login.*/);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user