Implements the Email Attendees feature which allows trainers to: - Email event attendees directly from the Event Summary page - Filter attendees by ticket type - Use a rich text editor to compose messages - Include CC recipients - Send personalized emails to selected attendees Includes unit tests, integration tests, and E2E tests to verify functionality. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
159 lines
No EOL
5.9 KiB
TypeScript
159 lines
No EOL
5.9 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
import { loginAsTrainer } from './utils/login-helpers';
|
|
import { createTestEvent } from './utils/event-helpers';
|
|
|
|
/**
|
|
* Email Attendees feature tests
|
|
* @group @email-attendees
|
|
*/
|
|
test.describe('Email Attendees Functionality', () => {
|
|
let eventId: string;
|
|
let eventTitle: string = 'Test Event for Email Attendees';
|
|
|
|
test.beforeAll(async ({ browser }) => {
|
|
// Create a test event with attendees
|
|
const context = await browser.newContext();
|
|
const page = await context.newPage();
|
|
|
|
await loginAsTrainer(page);
|
|
|
|
// Create a test event
|
|
eventId = await createTestEvent(page, {
|
|
title: eventTitle,
|
|
description: 'This is a test event for the email attendees functionality',
|
|
ticketType: 'General Admission',
|
|
price: '50.00'
|
|
});
|
|
|
|
// Add test attendees - In a real environment, you'd use the Tribe Tickets API
|
|
// For testing, we'd either mock this or use a separate helper to purchase tickets
|
|
|
|
await context.close();
|
|
});
|
|
|
|
test('can access Email Attendees page from Event Summary', async ({ page }) => {
|
|
// Login as trainer
|
|
await loginAsTrainer(page);
|
|
|
|
// Navigate to event summary
|
|
await page.goto(`/event-summary/?event_id=${eventId}`);
|
|
await expect(page).toHaveTitle(new RegExp(eventTitle));
|
|
|
|
// Check that the Email Attendees button exists
|
|
const emailAttendeesButton = page.locator('a:text("Email Attendees")');
|
|
await expect(emailAttendeesButton).toBeVisible();
|
|
|
|
// Click Email Attendees button
|
|
await emailAttendeesButton.click();
|
|
|
|
// Verify we're on the Email Attendees page
|
|
await expect(page).toHaveURL(new RegExp(`/email-attendees/\\?event_id=${eventId}`));
|
|
await expect(page.locator('h1:text("Email Attendees")')).toBeVisible();
|
|
await expect(page.locator(`h2:text("${eventTitle}")`)).toBeVisible();
|
|
});
|
|
|
|
test('email form has all required elements', async ({ page }) => {
|
|
// Login and go to Email Attendees page
|
|
await loginAsTrainer(page);
|
|
await page.goto(`/email-attendees/?event_id=${eventId}`);
|
|
|
|
// Check for required form elements
|
|
await expect(page.locator('#email_subject')).toBeVisible();
|
|
await expect(page.locator('#email_cc')).toBeVisible();
|
|
|
|
// The rich text editor might be in an iframe, so check for either
|
|
const hasEditor = await page.locator('.wp-editor-area, #email_message').count() > 0;
|
|
expect(hasEditor).toBeTruthy();
|
|
|
|
// Check for recipients section
|
|
await expect(page.locator('h3:text("Recipients")')).toBeVisible();
|
|
|
|
// Check for Send Email button
|
|
await expect(page.locator('button[name="hvac_send_email"]')).toBeVisible();
|
|
});
|
|
|
|
test('can filter attendees by ticket type', async ({ page }) => {
|
|
// Login and go to Email Attendees page
|
|
await loginAsTrainer(page);
|
|
await page.goto(`/email-attendees/?event_id=${eventId}`);
|
|
|
|
// Check if there's a ticket type filter (may not be visible if only one ticket type)
|
|
const hasTicketTypeFilter = await page.locator('#ticket_type_filter').count() > 0;
|
|
|
|
if (hasTicketTypeFilter) {
|
|
// Select a ticket type
|
|
await page.selectOption('#ticket_type_filter', 'General Admission');
|
|
|
|
// Wait for page to refresh
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Verify URL contains the ticket type parameter
|
|
await expect(page).toHaveURL(new RegExp('ticket_type=General\\+Admission'));
|
|
|
|
// Verify attendees are filtered
|
|
const attendeeItems = page.locator('.hvac-attendee-item');
|
|
await expect(attendeeItems).toContainText(['General Admission']);
|
|
}
|
|
});
|
|
|
|
test('can select all attendees', async ({ page }) => {
|
|
// Login and go to Email Attendees page
|
|
await loginAsTrainer(page);
|
|
await page.goto(`/email-attendees/?event_id=${eventId}`);
|
|
|
|
// Get initial count of checked boxes
|
|
const initialCheckedCount = await page.locator('.hvac-attendee-checkbox:checked').count();
|
|
expect(initialCheckedCount).toBe(0);
|
|
|
|
// Click "Select All" checkbox
|
|
await page.locator('#select_all_attendees').click();
|
|
|
|
// Verify all checkboxes are now checked
|
|
const attendeeCheckboxes = page.locator('.hvac-attendee-checkbox');
|
|
const attendeeCount = await attendeeCheckboxes.count();
|
|
const checkedCount = await page.locator('.hvac-attendee-checkbox:checked').count();
|
|
|
|
expect(checkedCount).toBe(attendeeCount);
|
|
});
|
|
|
|
test('shows validation error when form is incomplete', async ({ page }) => {
|
|
// Login and go to Email Attendees page
|
|
await loginAsTrainer(page);
|
|
await page.goto(`/email-attendees/?event_id=${eventId}`);
|
|
|
|
// Submit form without filling required fields
|
|
await page.locator('button[name="hvac_send_email"]').click();
|
|
|
|
// Verify error message is shown
|
|
await expect(page.locator('.hvac-email-error')).toBeVisible();
|
|
await expect(page.locator('.hvac-email-error')).toContainText('fill in all required fields');
|
|
});
|
|
|
|
test('can send email to attendees', async ({ page }) => {
|
|
// Login and go to Email Attendees page
|
|
await loginAsTrainer(page);
|
|
await page.goto(`/email-attendees/?event_id=${eventId}`);
|
|
|
|
// Fill out the form
|
|
await page.fill('#email_subject', 'Test Email Subject');
|
|
|
|
// Fill the message (handling both regular textarea and TinyMCE)
|
|
if (await page.locator('#email_message').count() > 0) {
|
|
await page.fill('#email_message', 'This is a test email message.');
|
|
} else {
|
|
// For TinyMCE, we need to use the iframe
|
|
const frame = page.frameLocator('.wp-editor-container iframe');
|
|
await frame.locator('body').fill('This is a test email message.');
|
|
}
|
|
|
|
// Select recipients (first attendee)
|
|
await page.locator('.hvac-attendee-checkbox').first().check();
|
|
|
|
// Submit form
|
|
await page.locator('button[name="hvac_send_email"]').click();
|
|
|
|
// Verify success message
|
|
await expect(page.locator('.hvac-email-sent')).toBeVisible();
|
|
await expect(page.locator('.hvac-email-sent')).toContainText('Email successfully sent');
|
|
});
|
|
}); |