- Updated configuration files and documentation to use new staging domain - Created centralized URL configuration for tests - Updated page objects to use configuration instead of hardcoded URLs - Added script to automatically update test files with new domain 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
281 lines
No EOL
12 KiB
TypeScript
281 lines
No EOL
12 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
import { LoginPage } from './pages/LoginPage';
|
|
import { DashboardPage } from './pages/DashboardPage';
|
|
import { CreateEventPage } from './pages/CreateEventPage';
|
|
import { EventSummaryPage } from './pages/EventSummaryPage';
|
|
import { ModifyEventPage } from './pages/ModifyEventPage';
|
|
import { TEST_USERS } from './data/test-users';
|
|
import { TEST_EVENTS } from './data/test-events';
|
|
import { STAGING_URL, PATHS, TIMEOUTS } from './config/staging-config';
|
|
|
|
test.describe('Trainer User Journey', () => {
|
|
let loginPage: LoginPage;
|
|
let dashboardPage: DashboardPage;
|
|
let createEventPage: CreateEventPage;
|
|
let eventSummaryPage: EventSummaryPage;
|
|
let modifyEventPage: ModifyEventPage;
|
|
|
|
const trainer = TEST_USERS.trainer;
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
loginPage = new LoginPage(page);
|
|
dashboardPage = new DashboardPage(page);
|
|
createEventPage = new CreateEventPage(page);
|
|
eventSummaryPage = new EventSummaryPage(page);
|
|
modifyEventPage = new ModifyEventPage(page);
|
|
|
|
// Set base URL and timeout
|
|
page.context().setDefaultNavigationTimeout(TIMEOUTS.navigation);
|
|
await page.goto(STAGING_URL);
|
|
});
|
|
|
|
test('Step 1 & 2: Trainer Login', async ({ page }) => {
|
|
// Navigate to login page
|
|
await loginPage.navigateToLogin();
|
|
await expect(page).toHaveURL(/.*community-login/);
|
|
|
|
// Verify login form is visible
|
|
expect(await loginPage.isLoginFormVisible()).toBe(true);
|
|
|
|
// Login with test trainer credentials
|
|
await loginPage.login(trainer.username, trainer.password);
|
|
|
|
// Verify successful login and redirect to dashboard
|
|
await expect(page).toHaveURL(/.*hvac-dashboard/);
|
|
await page.screenshot({ path: 'test-results/screenshots/login-success.png' });
|
|
});
|
|
|
|
test('Step 3: Access Dashboard', async ({ page }) => {
|
|
// Login first
|
|
await loginPage.navigateToLogin();
|
|
await loginPage.login(trainer.username, trainer.password);
|
|
|
|
// Wait for dashboard to load
|
|
await page.waitForLoadState('networkidle');
|
|
await expect(page).toHaveURL(/hvac-dashboard/);
|
|
|
|
// Verify dashboard elements are visible
|
|
expect(await dashboardPage.isEventsTableVisible()).toBe(true);
|
|
|
|
// Get and verify statistics - fix to match actual properties
|
|
const stats = await dashboardPage.getStatistics();
|
|
expect(stats.totalEvents).toBeDefined();
|
|
expect(stats.upcomingEvents).toBeDefined();
|
|
expect(stats.pastEvents).toBeDefined();
|
|
expect(stats.revenue).toBeDefined();
|
|
|
|
await page.screenshot({ path: 'test-results/screenshots/dashboard-view.png' });
|
|
});
|
|
|
|
test('Step 4a: Create Event', async ({ page }) => {
|
|
// Login and navigate to dashboard
|
|
await loginPage.navigateToLogin();
|
|
await loginPage.login(trainer.username, trainer.password);
|
|
|
|
// Click create event button
|
|
await dashboardPage.clickCreateEvent();
|
|
await expect(page).toHaveURL(/.*manage-event/);
|
|
|
|
// Fill event details
|
|
const eventData = TEST_EVENTS.basicEvent;
|
|
await createEventPage.fillEventDetails(eventData);
|
|
|
|
// Submit event
|
|
await createEventPage.submitEvent();
|
|
|
|
// Verify event creation - we remain on the manage-event page but with different content
|
|
await expect(page).toHaveURL(/manage-event/);
|
|
|
|
// Check for success indicator - either the submit button is gone or we see our event title
|
|
// Try multiple ways to verify successful submission
|
|
const submitButtonGone = await page.locator(createEventPage['submitButton']).isHidden().catch(() => true);
|
|
const eventTitleFilled = await page.inputValue('input[name="post_title"]') === eventData.title;
|
|
const viewYourEventsButtonVisible = await page.locator('text="VIEW YOUR SUBMITTED EVENTS"').isVisible().catch(() => false);
|
|
|
|
expect(submitButtonGone || eventTitleFilled || viewYourEventsButtonVisible).toBeTruthy();
|
|
|
|
await page.screenshot({ path: 'test-results/screenshots/event-created.png' });
|
|
|
|
// Go back to dashboard for next test
|
|
await page.goto(PATHS.dashboard);
|
|
});
|
|
|
|
test('Step 4b: Manage Events - View Event List', async ({ page }) => {
|
|
// Login
|
|
await loginPage.navigateToLogin();
|
|
await loginPage.login(trainer.username, trainer.password);
|
|
|
|
// Verify events table is visible
|
|
expect(await dashboardPage.isEventsTableVisible()).toBe(true);
|
|
|
|
// Get event count
|
|
const eventCount = await dashboardPage.getEventCount();
|
|
|
|
// If there are events, verify we can read the data
|
|
if (eventCount > 0) {
|
|
const eventData = await dashboardPage.getEventRowData(0);
|
|
expect(eventData.name).toBeTruthy();
|
|
expect(eventData.date).toBeTruthy();
|
|
expect(eventData.status).toBeTruthy();
|
|
} else {
|
|
// If no events, verify the "No events found" message is displayed
|
|
const noEventsMessage = await page.locator('text="No events found."').isVisible();
|
|
expect(noEventsMessage).toBe(true);
|
|
}
|
|
|
|
// Verify filter tabs are present
|
|
const filterTabs = ['ALL', 'PUBLISH', 'DRAFT', 'PENDING', 'PRIVATE'];
|
|
for (const filter of filterTabs) {
|
|
const filterVisible = await page.locator(`a:has-text("${filter}")`).isVisible();
|
|
expect(filterVisible).toBe(true);
|
|
}
|
|
});
|
|
|
|
test('Step 4c: Manage Events - Modify Event', async ({ page }) => {
|
|
// This test assumes there's at least one event to modify
|
|
// In a real scenario, we'd create one first
|
|
|
|
// Login
|
|
await loginPage.navigateToLogin();
|
|
await loginPage.login(trainer.username, trainer.password);
|
|
|
|
// Get first event and click it
|
|
const eventCount = await dashboardPage.getEventCount();
|
|
if (eventCount > 0) {
|
|
const eventData = await dashboardPage.getEventRowData(0);
|
|
await dashboardPage.clickEventName(eventData.name);
|
|
|
|
// Should be on event summary page
|
|
await expect(page).toHaveURL(/.*event-summary/);
|
|
|
|
// Click Edit Event
|
|
await eventSummaryPage.clickEditEvent();
|
|
await expect(page).toHaveURL(/.*modify-event/);
|
|
|
|
// Modify event details
|
|
const updatedEvent = {
|
|
...TEST_EVENTS.basicEvent,
|
|
title: 'Updated HVAC Training',
|
|
description: 'Updated description for the training event.'
|
|
};
|
|
|
|
await modifyEventPage.fillEventDetails(updatedEvent);
|
|
await modifyEventPage.updateEvent();
|
|
|
|
// Verify update success
|
|
await expect(page).toHaveURL(/.*dashboard|event-summary/);
|
|
await page.screenshot({ path: 'test-results/screenshots/event-updated.png' });
|
|
}
|
|
});
|
|
|
|
test('Step 5 & 6: View Event Statistics and Order Details', async ({ page }) => {
|
|
// Login
|
|
await loginPage.navigateToLogin();
|
|
await loginPage.login(trainer.username, trainer.password);
|
|
|
|
// Get first event and navigate to it
|
|
const eventCount = await dashboardPage.getEventCount();
|
|
if (eventCount > 0) {
|
|
const eventData = await dashboardPage.getEventRowData(0);
|
|
await dashboardPage.clickEventName(eventData.name);
|
|
|
|
// Should be on event summary page
|
|
await expect(page).toHaveURL(/.*event-summary/);
|
|
|
|
// Get event details
|
|
const details = await eventSummaryPage.getEventDetails();
|
|
expect(details.title).toBeTruthy();
|
|
expect(details.date).toBeTruthy();
|
|
expect(details.location).toBeTruthy();
|
|
|
|
// Check if transactions table is visible
|
|
const hasTransactions = await eventSummaryPage.isTransactionsTableVisible();
|
|
|
|
if (hasTransactions) {
|
|
const transactionCount = await eventSummaryPage.getTransactionCount();
|
|
|
|
if (transactionCount > 0) {
|
|
const transactionData = await eventSummaryPage.getTransactionData(0);
|
|
expect(transactionData.purchaserName).toBeTruthy();
|
|
expect(transactionData.revenue).toBeTruthy();
|
|
}
|
|
}
|
|
|
|
await page.screenshot({ path: 'test-results/screenshots/event-summary.png' });
|
|
}
|
|
});
|
|
|
|
test('Step 7 & 8: View Attendee Details', async ({ page }) => {
|
|
// Login
|
|
await loginPage.navigateToLogin();
|
|
await loginPage.login(trainer.username, trainer.password);
|
|
|
|
// Navigate to event with attendees
|
|
const eventCount = await dashboardPage.getEventCount();
|
|
if (eventCount > 0) {
|
|
const eventData = await dashboardPage.getEventRowData(0);
|
|
|
|
// Only proceed if event has sold tickets
|
|
if (parseInt(eventData.soldTickets) > 0) {
|
|
await dashboardPage.clickEventName(eventData.name);
|
|
|
|
// Check transactions table
|
|
const hasTransactions = await eventSummaryPage.isTransactionsTableVisible();
|
|
|
|
if (hasTransactions && await eventSummaryPage.getTransactionCount() > 0) {
|
|
const transaction = await eventSummaryPage.getTransactionData(0);
|
|
|
|
// Click purchaser name to view details
|
|
await eventSummaryPage.clickPurchaserName(transaction.purchaserName);
|
|
|
|
// Should navigate to order summary
|
|
await expect(page).toHaveURL(/.*order-summary/);
|
|
await page.screenshot({ path: 'test-results/screenshots/attendee-details.png' });
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// Phase 2 and Phase 3 tests would be implemented when those features are deployed
|
|
test.skip('Step 9: Email Communication (Phase 2)', async ({ page }) => {
|
|
// This will be implemented when Phase 2 is deployed
|
|
});
|
|
|
|
test.skip('Step 10: Attendee Check-in', async ({ page }) => {
|
|
// This will be implemented when the feature is available
|
|
});
|
|
|
|
test.skip('Step 11: Certificate Generation (Phase 3)', async ({ page }) => {
|
|
// This will be implemented when Phase 3 is deployed
|
|
});
|
|
});
|
|
|
|
// Error Scenario Tests
|
|
test.describe('Trainer Journey - Error Scenarios', () => {
|
|
let loginPage: LoginPage;
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
loginPage = new LoginPage(page);
|
|
await page.goto(STAGING_URL);
|
|
});
|
|
|
|
test('Invalid Login Credentials', async ({ page }) => {
|
|
await loginPage.navigateToLogin();
|
|
await loginPage.login('invalid_user', 'wrong_password');
|
|
|
|
// Should remain on login page
|
|
await expect(page).toHaveURL(/.*community-login/);
|
|
|
|
// Error message should be visible
|
|
const errorMessage = await loginPage.getErrorMessage();
|
|
expect(errorMessage).toContain('Invalid username or password');
|
|
});
|
|
|
|
test('Access Dashboard Without Login', async ({ page }) => {
|
|
// Try to access dashboard directly
|
|
await page.goto(PATHS.dashboard);
|
|
|
|
// Should be redirected to login
|
|
await expect(page).toHaveURL(/.*community-login/);
|
|
});
|
|
}); |