import { describe, it, expect, beforeAll } from 'vitest'; import { PrismaClient } from '@prisma/client'; import { aiService } from '../../src/services/ai'; import * as path from 'path'; import * as dotenv from 'dotenv'; dotenv.config({ path: path.join(__dirname, '../../../../../.env') }); const prisma = new PrismaClient(); const KAOLACK_PHONE = '221770000003'; describe('Kaolack Elite Journey Simulation', () => { let trackId: string; let userId: string; beforeAll(async () => { // 1. Cleanup before test await prisma.userProgress.deleteMany({ where: { user: { phone: KAOLACK_PHONE } } }); await prisma.response.deleteMany({ where: { user: { phone: KAOLACK_PHONE } } }); await prisma.enrollment.deleteMany({ where: { user: { phone: KAOLACK_PHONE } } }); await prisma.message.deleteMany({ where: { user: { phone: KAOLACK_PHONE } } }); await prisma.businessProfile.deleteMany({ where: { user: { phone: KAOLACK_PHONE } } }); await prisma.user.deleteMany({ where: { phone: KAOLACK_PHONE } }); const track = await prisma.track.findFirst({ where: { language: 'FR', title: { contains: "Comprendre" } } }); if (!track) throw new Error("Track T1-FR non trouvé."); trackId = track.id; // 2. User Creation (Grains de Kaolack) const user = await prisma.user.create({ data: { phone: KAOLACK_PHONE, name: 'Grains de Kaolack', language: 'FR', activity: 'Transformation de céréales locales (Mil, Maïs)', city: 'Kaolack', businessProfile: { create: { activityLabel: 'Grains de Kaolack - Transformation Céréalière', locationCity: 'Kaolack', marketData: { source: "ANSD 2023", population_kaolack: "300,000", } as any, competitorList: ["Importations riz/blé"], financialProjections: { revenueY1: "12 000 000 FCFA" }, fundingAsk: "8 000 000 FCFA pour automatisation" } } } as any, include: { businessProfile: true } as any }) as any; userId = user.id; // Mock an enrollment await prisma.enrollment.create({ data: { userId, trackId, status: 'COMPLETED', currentDay: 13 } as any }); }); it('should generate high-density Pitch Deck data from business profile', async () => { const user = await prisma.user.findUnique({ where: { id: userId }, include: { businessProfile: true } }) as any; const userContext = `AUDIT : Transformation de Céréales à Kaolack.`; const deckData = await aiService.generatePitchDeckData(userContext, 'FR', user.businessProfile); // Verify Genspark-Standard Requirements are met in the generation: expect(deckData).toBeDefined(); // Ensure no arrays of weak points - strict storytelling check via length/content expect(deckData.slides.length).toBeGreaterThan(5); const marketSlide = deckData.slides.find(s => s.title.toLowerCase().includes('marché') || s.title.toLowerCase().includes('market')); expect(marketSlide).toBeDefined(); // The market slide must mention Kaolack sourced from ANSD const marketContent = ((marketSlide?.content || []).join(' ') + ' ' + (marketSlide?.notes || '')).toLowerCase(); expect(marketContent).toContain('ansd'); expect(marketContent).toContain('300,000'); }, 60000); // 60s timeout for OpenAI API call it('should generate a One-Pager successfully', async () => { const user = await prisma.user.findUnique({ where: { id: userId }, include: { businessProfile: true } }) as any; const userContext = `AUDIT : Kaolack Céréales.`; const pdfData = await aiService.generateOnePagerData(userContext, 'FR', user.businessProfile); expect(pdfData).toBeDefined(); expect(pdfData.title).toBeDefined(); // Zod validation is implicitly guaranteed by the provider's `parse` returns if no exception is thrown. }, 60000); });