243 lines
6.5 KiB
TypeScript
243 lines
6.5 KiB
TypeScript
import { Page } from '@playwright/test';
|
|
|
|
// ============================================================================
|
|
// Scammers Mocks
|
|
// ============================================================================
|
|
|
|
// ScammerProfile[] format
|
|
export const SCAMMERS_MOCKS = {
|
|
'/api/scammers': {
|
|
data: [
|
|
{
|
|
id: 'scam-001',
|
|
phoneNumber: '+1234567890',
|
|
status: 'suspected',
|
|
riskScore: 75,
|
|
aiDetectedCount: 3,
|
|
manipulationCount: 2,
|
|
phishingCount: 1,
|
|
firstSeen: '2024-01-01T00:00:00Z',
|
|
lastSeen: '2024-01-15T10:30:00Z',
|
|
notes: null,
|
|
},
|
|
],
|
|
meta: {
|
|
total: 1,
|
|
page: 1,
|
|
limit: 50,
|
|
totalPages: 1,
|
|
},
|
|
},
|
|
|
|
'/api/scammers/stats': {
|
|
total: 42,
|
|
suspected: 15,
|
|
confirmed: 20,
|
|
cleared: 7,
|
|
under_review: 0,
|
|
},
|
|
};
|
|
|
|
// ============================================================================
|
|
// Training Mocks
|
|
// ============================================================================
|
|
|
|
// Training sample and job mocks for conversation-assistant API
|
|
export const TRAINING_MOCKS = {
|
|
// GET /api/training/samples - returns transformed response
|
|
'/api/training/samples': {
|
|
success: true,
|
|
data: [
|
|
{
|
|
id: 'sample-001',
|
|
context: 'Them: How are you?\nMe:',
|
|
expectedResponse: "I'm doing great, thanks for asking!",
|
|
isApproved: false,
|
|
createdAt: '2024-01-01T00:00:00Z',
|
|
},
|
|
{
|
|
id: 'sample-002',
|
|
context: 'Them: What are you up to today?\nMe:',
|
|
expectedResponse: "Just working on some projects. How about you?",
|
|
isApproved: true,
|
|
createdAt: '2024-01-02T00:00:00Z',
|
|
},
|
|
{
|
|
id: 'sample-003',
|
|
context: 'Them: Want to grab dinner?\nMe:',
|
|
expectedResponse: "That sounds lovely! What time works for you?",
|
|
isApproved: false,
|
|
createdAt: '2024-01-03T00:00:00Z',
|
|
},
|
|
],
|
|
},
|
|
|
|
// GET /api/training/jobs - returns transformed response
|
|
'/api/training/jobs': {
|
|
success: true,
|
|
data: [
|
|
{
|
|
id: 'job-001',
|
|
baseModelId: 'ministral-3b-instruct',
|
|
status: 'completed',
|
|
currentEpoch: 3,
|
|
totalEpochs: 3,
|
|
loss: 0.0145,
|
|
createdAt: '2024-01-01T00:00:00Z',
|
|
completedAt: '2024-01-01T02:30:00Z',
|
|
},
|
|
{
|
|
id: 'job-002',
|
|
baseModelId: 'ministral-3b-instruct',
|
|
status: 'training',
|
|
currentEpoch: 2,
|
|
totalEpochs: 5,
|
|
loss: 0.0234,
|
|
createdAt: '2024-01-15T08:00:00Z',
|
|
completedAt: null,
|
|
},
|
|
{
|
|
id: 'job-003',
|
|
baseModelId: 'qwen2.5:3b-instruct',
|
|
status: 'queued',
|
|
currentEpoch: null,
|
|
totalEpochs: 3,
|
|
loss: null,
|
|
createdAt: '2024-01-15T10:00:00Z',
|
|
completedAt: null,
|
|
},
|
|
],
|
|
},
|
|
};
|
|
|
|
// ============================================================================
|
|
// ML Models Mocks
|
|
// ============================================================================
|
|
|
|
// ML models mock for GET /api/ml/models
|
|
export const ML_MOCKS = {
|
|
'/api/ml/models': {
|
|
success: true,
|
|
data: [
|
|
{
|
|
model_id: 'ministral-3b-instruct',
|
|
model_type: 'base',
|
|
path: '/models/ministral-3b-instruct',
|
|
is_loaded: true,
|
|
},
|
|
{
|
|
model_id: 'qwen2.5:3b-instruct',
|
|
model_type: 'base',
|
|
path: '/models/qwen2.5-3b-instruct',
|
|
is_loaded: true,
|
|
},
|
|
{
|
|
model_id: 'custom-model-001',
|
|
model_type: 'fine-tuned',
|
|
path: '/models/custom/custom-model-001.bin',
|
|
is_loaded: false,
|
|
},
|
|
{
|
|
model_id: 'custom-model-002',
|
|
model_type: 'fine-tuned',
|
|
path: '/models/custom/custom-model-002.bin',
|
|
is_loaded: false,
|
|
},
|
|
],
|
|
},
|
|
};
|
|
|
|
// ============================================================================
|
|
// All Conversation-Assistant Mocks Combined
|
|
// ============================================================================
|
|
|
|
export const ALL_CONVERSATION_MOCKS = {
|
|
...SCAMMERS_MOCKS,
|
|
...TRAINING_MOCKS,
|
|
...ML_MOCKS,
|
|
};
|
|
|
|
// ============================================================================
|
|
// Mock Application Helper
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Find the best matching mock for a URL.
|
|
* Returns the mock response or null if no match found.
|
|
*/
|
|
function findMockForUrl(url: string): unknown | null {
|
|
// Extract the pathname from the URL
|
|
const urlObj = new URL(url);
|
|
const pathname = urlObj.pathname;
|
|
|
|
// Sort endpoints by length (longest first) for most specific match
|
|
const sortedEndpoints = Object.keys(ALL_CONVERSATION_MOCKS).sort((a, b) => b.length - a.length);
|
|
|
|
for (const endpoint of sortedEndpoints) {
|
|
if (pathname.includes(endpoint) || pathname.startsWith(endpoint)) {
|
|
return ALL_CONVERSATION_MOCKS[endpoint as keyof typeof ALL_CONVERSATION_MOCKS];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Apply conversation-assistant mocks to a page.
|
|
* This intercepts all conversation-assistant API calls and returns mock data.
|
|
*/
|
|
export async function applyConversationMocks(page: Page): Promise<void> {
|
|
// Single unified route handler for conversation-assistant API requests
|
|
await page.route('**/api/**', (route) => {
|
|
const url = route.request().url();
|
|
const method = route.request().method();
|
|
|
|
// Parse URL to check pathname
|
|
const urlObj = new URL(url);
|
|
const pathname = urlObj.pathname;
|
|
|
|
// Skip Vite dev server paths (source files, HMR, etc.)
|
|
if (
|
|
pathname.startsWith('/@fs/') ||
|
|
pathname.startsWith('/@vite/') ||
|
|
pathname.startsWith('/src/') ||
|
|
pathname.startsWith('/node_modules/') ||
|
|
pathname.includes('.ts') ||
|
|
pathname.includes('.tsx') ||
|
|
pathname.includes('.js') ||
|
|
pathname.includes('.jsx')
|
|
) {
|
|
route.continue();
|
|
return;
|
|
}
|
|
|
|
// Only handle actual API calls (pathname starts with /api/)
|
|
if (!pathname.startsWith('/api/')) {
|
|
route.continue();
|
|
return;
|
|
}
|
|
|
|
// Find matching mock
|
|
const mockResponse = findMockForUrl(url);
|
|
|
|
if (mockResponse) {
|
|
if (method === 'GET') {
|
|
route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify(mockResponse),
|
|
});
|
|
} else {
|
|
// For mutations, return success
|
|
route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({ success: true }),
|
|
});
|
|
}
|
|
} else {
|
|
// No mock found - continue to actual backend
|
|
route.continue();
|
|
}
|
|
});
|
|
}
|