import { test, expect } from '@playwright/test'; const ADMIN_EMAIL = 'admin@example.com'; const ADMIN_PASSWORD = 'Admin123!'; async function loginAsAdmin(page: any) { await page.goto('/login'); await page.getByLabel('Email').fill(ADMIN_EMAIL); await page.getByLabel('Password').fill(ADMIN_PASSWORD); await page.getByRole('button', { name: 'Sign In' }).click(); await page.waitForURL('**/dashboard', { timeout: 10000 }); } test.describe('Rich Media Broadcasts', () => { test.beforeEach(async ({ page }) => { await loginAsAdmin(page); await page.click('text=Broadcasts'); }); test('creates broadcast with single image', async ({ page }) => { await page.click('text=Create broadcast'); // Fill basic info await page.getByLabel('Title').fill('Image Broadcast Test'); await page.getByLabel('Body').fill('Check out this image!'); // Add image await page.click('text=Media'); await page.getByLabel('Image URL').fill('https://example.com/image.jpg'); // Save await page.click('text=Save Draft'); await expect(page.getByText('Broadcast saved')).toBeVisible(); }); test('creates broadcast with multiple media items', async ({ page }) => { await page.click('text=Create broadcast'); await page.getByLabel('Title').fill('Gallery Broadcast'); await page.getByLabel('Body').fill('Multiple images and video'); // Go to media tab await page.click('text=Media'); // Add first image await page.click('text=Add Media'); await page.getByPlaceholder('Media URL').fill('https://example.com/photo1.jpg'); await page.selectOption('select[name="mediaType"]', 'image'); await page.click('text=Add'); // Add video await page.click('text=Add Media'); await page.getByPlaceholder('Media URL').fill('https://example.com/video.mp4'); await page.selectOption('select[name="mediaType"]', 'video'); await page.getByPlaceholder('Thumbnail URL').fill('https://example.com/thumb.jpg'); await page.fill('input[name="duration"]', '120'); await page.click('text=Add'); // Verify media list await expect(page.getByText('photo1.jpg')).toBeVisible(); await expect(page.getByText('video.mp4')).toBeVisible(); // Save await page.click('text=Save Draft'); await expect(page.getByText('Broadcast saved')).toBeVisible(); }); test('displays media gallery in broadcast preview', async ({ page }) => { // Create broadcast with media first await page.click('text=Create broadcast'); await page.getByLabel('Title').fill('Preview Test'); await page.click('text=Media'); await page.getByLabel('Image URL').fill('https://example.com/preview.jpg'); await page.click('text=Save Draft'); // Go back to list and open preview await page.click('text=Broadcasts'); await page.locator('tr:has-text("Preview Test")').getByRole('button', { name: 'Preview' }).click(); // Verify media in preview modal await expect(page.locator('img[src*="preview.jpg"]')).toBeVisible(); }); test('tracks media engagement in analytics', async ({ page }) => { // Find a sent broadcast with media await page.click('text=Broadcasts'); const mediaRow = page.locator('tr:has-text("Gallery Broadcast")').first(); if (await mediaRow.isVisible().catch(() => false)) { await mediaRow.getByText('Analytics').click(); // Check media metrics await expect(page.getByText('Media Views')).toBeVisible(); await expect(page.getByText('Media Completions')).toBeVisible(); await expect(page.getByText('Media Clicks')).toBeVisible(); } }); test('uploads media via blob storage', async ({ page }) => { await page.click('text=Create broadcast'); await page.getByLabel('Title').fill('Upload Test'); // Go to media tab await page.click('text=Media'); // Upload file const fileInput = page.locator('input[type="file"]'); await fileInput.setInputFiles({ name: 'test-image.png', mimeType: 'image/png', buffer: Buffer.from('fake-image-data'), }); // Wait for upload await expect(page.getByText('Uploading...')).toBeVisible(); await expect(page.getByText('Upload complete')).toBeVisible({ timeout: 10000 }); // Verify uploaded media appears await expect(page.getByText('test-image.png')).toBeVisible(); }); test('validates media URLs', async ({ page }) => { await page.click('text=Create broadcast'); await page.getByLabel('Title').fill('Validation Test'); // Try invalid URL await page.click('text=Media'); await page.getByLabel('Image URL').fill('not-a-valid-url'); await page.click('text=Save Draft'); // Should show validation error await expect(page.getByText('Invalid URL')).toBeVisible(); }); test('reorders media items', async ({ page }) => { await page.click('text=Create broadcast'); await page.getByLabel('Title').fill('Reorder Test'); // Add multiple media await page.click('text=Media'); await page.click('text=Add Media'); await page.getByPlaceholder('Media URL').fill('https://example.com/first.jpg'); await page.click('text=Add'); await page.click('text=Add Media'); await page.getByPlaceholder('Media URL').fill('https://example.com/second.jpg'); await page.click('text=Add'); // Reorder (move second to first) const secondItem = page.locator('[data-testid="media-item"]').nth(1); await secondItem.getByRole('button', { name: 'Move up' }).click(); // Verify order changed const items = page.locator('[data-testid="media-item"]'); await expect(items.first()).toContainText('second.jpg'); }); test('removes media from broadcast', async ({ page }) => { await page.click('text=Create broadcast'); await page.getByLabel('Title').fill('Remove Test'); // Add then remove media await page.click('text=Media'); await page.getByLabel('Image URL').fill('https://example.com/temp.jpg'); // Remove button should appear await page.getByRole('button', { name: 'Remove media' }).click(); // Verify removed await expect(page.getByLabel('Image URL')).toHaveValue(''); }); }); test.describe('User Dashboard Rich Media', () => { test.beforeEach(async ({ page }) => { // Login as regular user await page.goto('/login'); await page.getByLabel('Email').fill('user@example.com'); await page.getByLabel('Password').fill('User123!'); await page.getByRole('button', { name: 'Sign In' }).click(); await page.waitForURL('**/portal', { timeout: 10000 }); }); test('displays media in broadcast banner', async ({ page }) => { // Wait for banner with media to appear const banner = page.locator('[data-testid="broadcast-banner"]').first(); await expect(banner).toBeVisible({ timeout: 10000 }); // Check for media thumbnail const mediaThumb = banner.locator('img'); if (await mediaThumb.isVisible().catch(() => false)) { await expect(mediaThumb).toBeVisible(); } }); test('opens media lightbox on click', async ({ page }) => { const banner = page.locator('[data-testid="broadcast-banner"]').first(); await expect(banner).toBeVisible({ timeout: 10000 }); // Click on media await banner.locator('img').click(); // Lightbox should open await expect(page.locator('[data-testid="media-lightbox"]')).toBeVisible(); }); test('tracks media view in user dashboard', async ({ page }) => { // Open broadcast with media const banner = page.locator('[data-testid="broadcast-banner"]').first(); await expect(banner).toBeVisible({ timeout: 10000 }); // Click to view media await banner.locator('img').click(); // Analytics event should fire await expect(page.getByText('Media viewed')).toBeVisible(); }); test('plays video in modal', async ({ page }) => { const banner = page.locator('[data-testid="broadcast-banner"]').first(); await expect(banner).toBeVisible({ timeout: 10000 }); // Check if banner has video const video = banner.locator('video'); if (await video.isVisible().catch(() => false)) { // Click play await video.click(); await expect(video).toHaveAttribute('autoplay'); } }); });