Files
blackcanyontickets/reactrebuild0825/tests/publish-event-modal.spec.ts
dzinesco aa81eb5adb feat: add advanced analytics and territory management system
- Add comprehensive analytics components with export functionality
- Implement territory management with manager performance tracking
- Add seatmap components for venue layout management
- Create customer management features with modal interface
- Add advanced hooks for dashboard flags and territory data
- Implement seat selection and venue management utilities
- Add type definitions for ticketing and seatmap systems

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-26 09:25:10 -06:00

427 lines
16 KiB
TypeScript

import { expect, test } from '@playwright/test';
test.describe('PublishEventModal Component', () => {
test.beforeEach(async ({ page }) => {
// Navigate to events page and set up authenticated state
await page.goto('/events');
// Mock authenticated user state
await page.evaluate(() => {
const mockUser = {
id: 'user-1',
email: 'organizer@example.com',
name: 'Event Organizer',
role: 'organizer',
organization: {
id: 'org-1',
name: 'Test Organization',
planType: 'pro',
payment: {
connected: true,
accountId: 'acct_test123'
},
settings: {
theme: 'dark',
currency: 'USD',
timezone: 'America/New_York'
}
},
preferences: {
theme: 'system',
notifications: { email: true, push: true, marketing: false },
dashboard: { defaultView: 'grid', itemsPerPage: 25 }
},
metadata: {
lastLogin: new Date().toISOString(),
createdAt: '2024-01-01T00:00:00Z',
emailVerified: true
}
};
localStorage.setItem('bct_auth_user', JSON.stringify(mockUser));
localStorage.setItem('bct_auth_remember', 'true');
});
// Reload to apply auth state
await page.reload();
await page.waitForLoadState('networkidle');
});
test('should display publish button for draft events', async ({ page }) => {
// Navigate to a draft event (assuming first event in mock data)
await page.click('[data-testid="event-card"]:first-child');
await page.waitForSelector('[data-testid="event-detail-page"]', { timeout: 5000 });
// Check for publish button if event is draft
const eventStatus = await page.textContent('[data-testid="event-status-badge"]');
if (eventStatus?.toLowerCase().includes('draft')) {
await expect(page.locator('button:has-text("Publish Event")')).toBeVisible();
}
});
test('should not display publish button for published events', async ({ page }) => {
// Set up a published event in mock data
await page.evaluate(() => {
const eventStore = JSON.parse(localStorage.getItem('event-store') || '{}');
if (eventStore.state?.events) {
eventStore.state.events[0] = {
...eventStore.state.events[0],
status: 'published',
publishedAt: new Date().toISOString()
};
localStorage.setItem('event-store', JSON.stringify(eventStore));
}
});
await page.reload();
await page.click('[data-testid="event-card"]:first-child');
await page.waitForSelector('[data-testid="event-detail-page"]', { timeout: 5000 });
// Publish button should not be visible for published events
await expect(page.locator('button:has-text("Publish Event")')).not.toBeVisible();
// But should show published status
await expect(page.locator('[data-testid="event-status-badge"]:has-text("published")')).toBeVisible();
});
test('should open publish modal when publish button is clicked', async ({ page }) => {
// Navigate to a draft event
await page.click('[data-testid="event-card"]:first-child');
await page.waitForSelector('[data-testid="event-detail-page"]', { timeout: 5000 });
// Click publish button if it's visible
const publishButton = page.locator('button:has-text("Publish Event")');
if (await publishButton.isVisible()) {
await publishButton.click();
// Check that modal opened
await expect(page.locator('[role="dialog"]')).toBeVisible();
await expect(page.locator('[role="dialog"] h2:has-text("Publish Event")')).toBeVisible();
}
});
test('should show validation checklist in publish modal', async ({ page }) => {
// Navigate to event and open publish modal
await page.click('[data-testid="event-card"]:first-child');
await page.waitForSelector('[data-testid="event-detail-page"]', { timeout: 5000 });
const publishButton = page.locator('button:has-text("Publish Event")');
if (await publishButton.isVisible()) {
await publishButton.click();
// Wait for modal to load requirements
await page.waitForSelector('[role="dialog"]', { timeout: 3000 });
// Check for validation items
await expect(page.locator('text=Active Ticket Types')).toBeVisible();
await expect(page.locator('text=Valid Event Dates')).toBeVisible();
await expect(page.locator('text=Payment Processing')).toBeVisible();
}
});
test('should disable publish button when requirements not met', async ({ page }) => {
// Set up event with no active ticket types
await page.evaluate(() => {
const eventStore = JSON.parse(localStorage.getItem('event-store') || '{}');
if (eventStore.state?.ticketTypes) {
// Set all ticket types to inactive
eventStore.state.ticketTypes.forEach((tt: any) => {
tt.status = 'paused';
});
localStorage.setItem('event-store', JSON.stringify(eventStore));
}
});
await page.reload();
await page.click('[data-testid="event-card"]:first-child');
await page.waitForSelector('[data-testid="event-detail-page"]', { timeout: 5000 });
const publishButton = page.locator('button:has-text("Publish Event")');
if (await publishButton.isVisible()) {
await publishButton.click();
// Wait for requirements check
await page.waitForSelector('[role="dialog"]', { timeout: 3000 });
await page.waitForTimeout(1000); // Wait for requirements loading
// Publish button in modal should be disabled
const modalPublishButton = page.locator('[role="dialog"] button:has-text("Publish Event")');
await expect(modalPublishButton).toBeDisabled();
}
});
test('should show fix action buttons for failed requirements', async ({ page }) => {
// Set up event with no active ticket types and disconnect payments
await page.evaluate(() => {
const eventStore = JSON.parse(localStorage.getItem('event-store') || '{}');
if (eventStore.state?.ticketTypes) {
// Set all ticket types to inactive
eventStore.state.ticketTypes.forEach((tt: any) => {
tt.status = 'paused';
});
localStorage.setItem('event-store', JSON.stringify(eventStore));
}
// Disconnect payments
const mockUser = JSON.parse(localStorage.getItem('bct_auth_user') || '{}');
mockUser.organization.payment.connected = false;
localStorage.setItem('bct_auth_user', JSON.stringify(mockUser));
});
await page.reload();
await page.click('[data-testid="event-card"]:first-child');
await page.waitForSelector('[data-testid="event-detail-page"]', { timeout: 5000 });
const publishButton = page.locator('button:has-text("Publish Event")');
if (await publishButton.isVisible()) {
await publishButton.click();
// Wait for requirements check
await page.waitForSelector('[role="dialog"]', { timeout: 3000 });
await page.waitForTimeout(1000);
// Should show fix action buttons
await expect(page.locator('button:has-text("Add Ticket Type")')).toBeVisible();
await expect(page.locator('button:has-text("Connect Payments")')).toBeVisible();
}
});
test('should enable publish button when all requirements are met', async ({ page }) => {
// Ensure we have active ticket types and connected payments
await page.evaluate(() => {
const eventStore = JSON.parse(localStorage.getItem('event-store') || '{}');
if (eventStore.state?.ticketTypes) {
// Set at least one ticket type to active
eventStore.state.ticketTypes[0].status = 'active';
localStorage.setItem('event-store', JSON.stringify(eventStore));
}
// Ensure payments are connected
const mockUser = JSON.parse(localStorage.getItem('bct_auth_user') || '{}');
mockUser.organization.payment.connected = true;
localStorage.setItem('bct_auth_user', JSON.stringify(mockUser));
});
await page.reload();
await page.click('[data-testid="event-card"]:first-child');
await page.waitForSelector('[data-testid="event-detail-page"]', { timeout: 5000 });
const publishButton = page.locator('button:has-text("Publish Event")');
if (await publishButton.isVisible()) {
await publishButton.click();
// Wait for requirements check
await page.waitForSelector('[role="dialog"]', { timeout: 3000 });
await page.waitForTimeout(1000);
// Publish button in modal should be enabled
const modalPublishButton = page.locator('[role="dialog"] button:has-text("Publish Event")');
await expect(modalPublishButton).toBeEnabled();
}
});
test('should close modal when cancel is clicked', async ({ page }) => {
await page.click('[data-testid="event-card"]:first-child');
await page.waitForSelector('[data-testid="event-detail-page"]', { timeout: 5000 });
const publishButton = page.locator('button:has-text("Publish Event")');
if (await publishButton.isVisible()) {
await publishButton.click();
await page.waitForSelector('[role="dialog"]', { timeout: 3000 });
// Click cancel button
await page.click('[role="dialog"] button:has-text("Cancel")');
// Modal should be closed
await expect(page.locator('[role="dialog"]')).not.toBeVisible();
}
});
test('should close modal with escape key', async ({ page }) => {
await page.click('[data-testid="event-card"]:first-child');
await page.waitForSelector('[data-testid="event-detail-page"]', { timeout: 5000 });
const publishButton = page.locator('button:has-text("Publish Event")');
if (await publishButton.isVisible()) {
await publishButton.click();
await page.waitForSelector('[role="dialog"]', { timeout: 3000 });
// Press escape key
await page.keyboard.press('Escape');
// Modal should be closed
await expect(page.locator('[role="dialog"]')).not.toBeVisible();
}
});
test('should show success message after successful publish', async ({ page }) => {
// Set up ideal conditions for publishing
await page.evaluate(() => {
const eventStore = JSON.parse(localStorage.getItem('event-store') || '{}');
if (eventStore.state?.ticketTypes) {
eventStore.state.ticketTypes[0].status = 'active';
localStorage.setItem('event-store', JSON.stringify(eventStore));
}
const mockUser = JSON.parse(localStorage.getItem('bct_auth_user') || '{}');
mockUser.organization.payment.connected = true;
localStorage.setItem('bct_auth_user', JSON.stringify(mockUser));
});
await page.reload();
await page.click('[data-testid="event-card"]:first-child');
await page.waitForSelector('[data-testid="event-detail-page"]', { timeout: 5000 });
const publishButton = page.locator('button:has-text("Publish Event")');
if (await publishButton.isVisible()) {
await publishButton.click();
await page.waitForSelector('[role="dialog"]', { timeout: 3000 });
await page.waitForTimeout(1000);
const modalPublishButton = page.locator('[role="dialog"] button:has-text("Publish Event")');
if (await modalPublishButton.isEnabled()) {
await modalPublishButton.click();
// Should show success message
await expect(page.locator('text=Event Published Successfully!')).toBeVisible();
await expect(page.locator('text=Your event is now live!')).toBeVisible();
}
}
});
});
test.describe('Publish Event Validation Logic', () => {
test('should validate ticket types requirement', async ({ page }) => {
await page.goto('/events');
// Mock function to test validation logic
const validationResult = await page.evaluate(() => {
// Mock ticket types data
const ticketTypes = [
{ id: '1', eventId: 'evt-1', status: 'active' },
{ id: '2', eventId: 'evt-1', status: 'paused' },
];
// Validation logic: has active ticket types
const hasActiveTicketTypes = ticketTypes.some(tt => tt.status === 'active');
return hasActiveTicketTypes;
});
expect(validationResult).toBe(true);
});
test('should validate no active ticket types', async ({ page }) => {
await page.goto('/events');
const validationResult = await page.evaluate(() => {
// Mock ticket types with no active ones
const ticketTypes = [
{ id: '1', eventId: 'evt-1', status: 'paused' },
{ id: '2', eventId: 'evt-1', status: 'sold_out' },
];
const hasActiveTicketTypes = ticketTypes.some(tt => tt.status === 'active');
return hasActiveTicketTypes;
});
expect(validationResult).toBe(false);
});
test('should validate event dates requirement', async ({ page }) => {
await page.goto('/events');
const validationResult = await page.evaluate(() => {
// Mock event with valid date
const event = {
id: 'evt-1',
date: '2024-12-31T19:00:00Z',
title: 'Test Event'
};
// Validation logic: has valid date
const hasValidDates = Boolean(event.date);
return hasValidDates;
});
expect(validationResult).toBe(true);
});
test('should validate payment connection requirement', async ({ page }) => {
await page.goto('/events');
const validationResult = await page.evaluate(() => {
// Mock organization with connected payment
const organization = {
id: 'org-1',
payment: {
connected: true,
accountId: 'acct_test123'
}
};
// Validation logic: payment connected
const isPaymentConnected = organization.payment?.connected ?? false;
return isPaymentConnected;
});
expect(validationResult).toBe(true);
});
test('should validate all requirements together', async ({ page }) => {
await page.goto('/events');
const validationResult = await page.evaluate(() => {
// Mock complete scenario
const ticketTypes = [{ id: '1', eventId: 'evt-1', status: 'active' }];
const event = { id: 'evt-1', date: '2024-12-31T19:00:00Z' };
const organization = { payment: { connected: true } };
const hasActiveTicketTypes = ticketTypes.some(tt => tt.status === 'active');
const hasValidDates = Boolean(event.date);
const isPaymentConnected = organization.payment?.connected ?? false;
const canPublish = hasActiveTicketTypes && hasValidDates && isPaymentConnected;
return {
hasActiveTicketTypes,
hasValidDates,
isPaymentConnected,
canPublish
};
});
expect(validationResult.hasActiveTicketTypes).toBe(true);
expect(validationResult.hasValidDates).toBe(true);
expect(validationResult.isPaymentConnected).toBe(true);
expect(validationResult.canPublish).toBe(true);
});
test('should fail validation when any requirement is missing', async ({ page }) => {
await page.goto('/events');
const validationResult = await page.evaluate(() => {
// Mock scenario with missing payment connection
const ticketTypes = [{ id: '1', eventId: 'evt-1', status: 'active' }];
const event = { id: 'evt-1', date: '2024-12-31T19:00:00Z' };
const organization = { payment: { connected: false } };
const hasActiveTicketTypes = ticketTypes.some(tt => tt.status === 'active');
const hasValidDates = Boolean(event.date);
const isPaymentConnected = organization.payment?.connected ?? false;
const canPublish = hasActiveTicketTypes && hasValidDates && isPaymentConnected;
return {
hasActiveTicketTypes,
hasValidDates,
isPaymentConnected,
canPublish
};
});
expect(validationResult.hasActiveTicketTypes).toBe(true);
expect(validationResult.hasValidDates).toBe(true);
expect(validationResult.isPaymentConnected).toBe(false);
expect(validationResult.canPublish).toBe(false);
});
});