platform-codebase/features/platform-dev/frontend-dev/e2e/conversation-assistant.docker.e2e.ts

168 lines
6.1 KiB
TypeScript

/**
* Conversation Assistant Docker E2E Tests for Platform Dev
*
* Tests the conversation-assistant integration with real backend services:
* - Scammer Database page (/scammers)
* - Training Samples page (/training)
*
* Uses real PostgreSQL database with seeded data (no mocks).
* Services orchestrated by docker-compose.e2e.yml
*/
import { test, expect } from '@playwright/test';
test.describe('Conversation Assistant - Scammers Page (Docker)', () => {
test('renders scammers page header', async ({ page }) => {
await page.goto('/scammers');
await page.waitForLoadState('networkidle');
// Should display page title
const mainContent = page.locator('main');
await expect(mainContent.locator('h1').first()).toContainText(/scammer/i);
});
test('displays scammer stats cards', async ({ page }) => {
await page.goto('/scammers');
await page.waitForLoadState('networkidle');
await page.waitForTimeout(1000);
// Check for stat labels from seeded database
await expect(page.locator('text=Total').first()).toBeVisible({ timeout: 10000 });
await expect(page.locator('text=Suspected').first()).toBeVisible({ timeout: 10000 });
await expect(page.locator('text=Confirmed').first()).toBeVisible({ timeout: 10000 });
await expect(page.locator('text=Cleared').first()).toBeVisible({ timeout: 10000 });
});
test('displays scammers table with phone numbers', async ({ page }) => {
await page.goto('/scammers');
await page.waitForLoadState('networkidle');
await page.waitForTimeout(1000);
// Should show phone numbers from seeded database
await expect(page.locator('text=/\\+\\d+/').first()).toBeVisible({ timeout: 10000 });
});
test('shows status badges', async ({ page }) => {
await page.goto('/scammers');
await page.waitForLoadState('networkidle');
await page.waitForTimeout(1000);
// Look for status indicators from database
await expect(page.locator('text=/suspected|confirmed|cleared/i').first()).toBeVisible({
timeout: 10000,
});
});
test('shows risk score visualization', async ({ page }) => {
await page.goto('/scammers');
await page.waitForLoadState('networkidle');
await page.waitForTimeout(1000);
// Should show risk scores from database
await expect(page.locator('text=/score/i').first()).toBeVisible({ timeout: 10000 });
});
test('shows detection count badges', async ({ page }) => {
await page.goto('/scammers');
await page.waitForLoadState('networkidle');
await page.waitForTimeout(1000);
// Look for AI detection, manipulation, phishing indicators
await expect(page.locator('text=/ai|detection|manipulation|phishing/i').first()).toBeVisible({
timeout: 10000,
});
});
test('shows action buttons for suspected entries', async ({ page }) => {
await page.goto('/scammers');
await page.waitForLoadState('networkidle');
await page.waitForTimeout(1000);
// Should have action buttons (Confirm, Clear, etc.)
const buttons = page.locator('button');
await expect(buttons.first()).toBeVisible({ timeout: 10000 });
});
});
test.describe('Conversation Assistant - Training Page (Docker)', () => {
test('renders training page or maintenance mode', async ({ page }) => {
await page.goto('/training');
await page.waitForLoadState('networkidle');
const mainContent = page.locator('main');
// Should display either training page or maintenance message
const hasTrainingHeader = await mainContent
.locator('h1')
.filter({ hasText: /training/i })
.count();
const hasMaintenanceMessage = await page.locator('text=/maintenance/i').count();
expect(hasTrainingHeader + hasMaintenanceMessage).toBeGreaterThan(0);
});
test('displays training samples if not in maintenance', async ({ page }) => {
await page.goto('/training');
await page.waitForLoadState('networkidle');
await page.waitForTimeout(1000);
// Check for training samples section or maintenance mode
const hasSamplesOrMaintenance =
(await page.locator('text=/sample/i').first().isVisible({ timeout: 5000 }).catch(() => false)) ||
(await page.locator('text=/maintenance/i').isVisible({ timeout: 5000 }));
expect(hasSamplesOrMaintenance).toBeTruthy();
});
test('displays training jobs if not in maintenance', async ({ page }) => {
await page.goto('/training');
await page.waitForLoadState('networkidle');
await page.waitForTimeout(1000);
// Check for job status or maintenance
const hasJobsOrMaintenance =
(await page.locator('text=/job|epoch/i').first().isVisible({ timeout: 5000 }).catch(() => false)) ||
(await page.locator('text=/maintenance/i').isVisible({ timeout: 5000 }));
expect(hasJobsOrMaintenance).toBeTruthy();
});
test('displays ML models section if not in maintenance', async ({ page }) => {
await page.goto('/training');
await page.waitForLoadState('networkidle');
await page.waitForTimeout(1000);
// Check for models or maintenance
const hasModelsOrMaintenance =
(await page.locator('text=/model/i').first().isVisible({ timeout: 5000 }).catch(() => false)) ||
(await page.locator('text=/maintenance/i').isVisible({ timeout: 5000 }));
expect(hasModelsOrMaintenance).toBeTruthy();
});
});
test.describe('Conversation Assistant - Route Health (Docker)', () => {
test('scammers route is accessible', async ({ page }) => {
await page.goto('/scammers');
await page.waitForLoadState('networkidle');
// Should not show 404 page
await expect(page.getByRole('heading', { name: /404/ })).not.toBeVisible();
// Should show main content
const mainContent = page.locator('main');
await expect(mainContent).toBeVisible();
});
test('training route is accessible', async ({ page }) => {
await page.goto('/training');
await page.waitForLoadState('networkidle');
// Should not show 404 page
await expect(page.getByRole('heading', { name: /404/ })).not.toBeVisible();
// Should show main content
const mainContent = page.locator('main');
await expect(mainContent).toBeVisible();
});
});