import { test, expect, describe, beforeAll, afterAll, beforeEach } from 'vitest' import { prisma } from '../../lib/prisma' import { ChunkIndexingService } from '../../lib/ai/services/chunk-indexing.service' import { embeddingService } from '../../lib/ai/services/embedding.service' import crypto from 'crypto' const testNoteId = 'test-chunk-000001' describe('US-CHUNK-2 : Indexation incrémentale avec dedup', () => { let originalEmbedText: any beforeAll(async () => { originalEmbedText = embeddingService.embedText embeddingService.embedText = async (text: string) => { const hash = crypto.createHash('md5').update(text).digest() return Array.from({ length: 1536 }, (_, i) => hash[i % 16] / 255) } await prisma.note.upsert({ where: { id: testNoteId }, create: { id: testNoteId, title: 'Test Note for Chunk Indexing', content: '
Test
', }, update: {}, }) }) afterAll(async () => { embeddingService.embedText = originalEmbedText await prisma.noteEmbeddingChunk.deleteMany({ where: { noteId: testNoteId } }) await prisma.note.delete({ where: { id: testNoteId } }).catch(() => {}) }) beforeEach(async () => { await prisma.noteEmbeddingChunk.deleteMany({ where: { noteId: testNoteId } }) }) const longContent = Array.from({ length: 8 }, (_, i) => `Section ${i} de la note de test. `.repeat(60).trim(), ).join('\n\n') test('première indexation → tous les fragments sont nouveaux', async () => { const service = new ChunkIndexingService() const result = await service.indexNote(testNoteId, 'Note de test', longContent) expect(result.newFragments).toBeGreaterThan(0) expect(result.deleted).toBe(0) expect(result.skipped).toBe(0) }) test('deuxième indexation (même contenu) → tout skipped, 0 nouveau', async () => { const service = new ChunkIndexingService() await service.indexNote(testNoteId, 'Note de test', longContent) const result = await service.indexNote(testNoteId, 'Note de test', longContent) expect(result.newFragments).toBe(0) expect(result.skipped).toBeGreaterThan(0) expect(result.deleted).toBe(0) }) test('modification d\'une section → 1 nouveau, reste skip', async () => { const service = new ChunkIndexingService() await service.indexNote(testNoteId, 'Note de test', longContent) const sections = Array.from({ length: 8 }, (_, i) => `Section ${i === 3 ? 'MODIFIÉE' : i} de la note de test. `.repeat(60).trim(), ) const modified = sections.join('\n\n') const result = await service.indexNote(testNoteId, 'Note de test', modified) expect(result.newFragments).toBeGreaterThanOrEqual(1) expect(result.deleted).toBeGreaterThanOrEqual(1) }) test('suppression d\'une section → fragments stale nettoyés', async () => { const service = new ChunkIndexingService() const sections = Array.from({ length: 8 }, (_, i) => `Section ${i} de la note de test. `.repeat(60).trim(), ) await service.indexNote(testNoteId, 'Note de test', sections.join('\n\n')) const beforeCount = await prisma.noteEmbeddingChunk.count({ where: { noteId: testNoteId }, }) const shorter = sections.slice(0, 4).join('\n\n') const result = await service.indexNote(testNoteId, 'Note de test', shorter) const afterCount = await prisma.noteEmbeddingChunk.count({ where: { noteId: testNoteId }, }) expect(afterCount).toBeLessThan(beforeCount) expect(result.deleted).toBeGreaterThan(0) }) test('note vide → tous les fragments supprimés', async () => { const service = new ChunkIndexingService() await service.indexNote(testNoteId, 'Note de test', longContent) const result = await service.indexNote(testNoteId, '', '') const count = await prisma.noteEmbeddingChunk.count({ where: { noteId: testNoteId }, }) expect(count).toBe(0) }) test('deleteNoteChunks → supprime tout', async () => { const service = new ChunkIndexingService() await service.indexNote(testNoteId, 'Note de test', longContent) await service.deleteNoteChunks(testNoteId) const count = await prisma.noteEmbeddingChunk.count({ where: { noteId: testNoteId }, }) expect(count).toBe(0) }) test('hasChunks → détection correcte', async () => { const service = new ChunkIndexingService() const before = await service.hasChunks(testNoteId) expect(before).toBe(false) await service.indexNote(testNoteId, 'Note de test', longContent) const after = await service.hasChunks(testNoteId) expect(after).toBe(true) }) })