teqo-backup/tests/unit/campaignDemandTitle.unit.spec.ts

59 lines
2 KiB
TypeScript

// @vitest-environment node
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
const { generateTextMock, deepSeekMock } = vi.hoisted(() => ({
generateTextMock: vi.fn(),
deepSeekMock: vi.fn(() => 'mock-model'),
}))
vi.mock('ai', () => ({ generateText: generateTextMock }))
vi.mock('@ai-sdk/deepseek', () => ({ deepSeek: deepSeekMock }))
import { deriveDemandTitle } from '@/utilities/ai/campaignDemandTitle'
beforeEach(() => {
process.env.DEEPSEEK_API_KEY = 'test-deepseek-key'
generateTextMock.mockReset()
deepSeekMock.mockClear()
})
afterEach(() => {
delete process.env.DEEPSEEK_API_KEY
})
describe('deriveDemandTitle (B195)', () => {
it('devolve o título quando o modelo responde algo usável', async () => {
generateTextMock.mockResolvedValue({ text: 'Carro de som para a plenária' })
await expect(deriveDemandTitle('preciso de carro de som', 'transporte')).resolves.toBe(
'Carro de som para a plenária',
)
})
it('degrada para null sem chave, em erro ou com saída inutilizável', async () => {
delete process.env.DEEPSEEK_API_KEY
await expect(deriveDemandTitle('pedido')).resolves.toBeNull()
expect(generateTextMock).not.toHaveBeenCalled()
process.env.DEEPSEEK_API_KEY = 'test-deepseek-key'
generateTextMock.mockRejectedValue(new Error('provider down'))
await expect(deriveDemandTitle('pedido')).resolves.toBeNull()
generateTextMock.mockResolvedValue({ text: ' ' })
await expect(deriveDemandTitle('pedido')).resolves.toBeNull()
})
it('desliga o thinking e mantém teto de saída acima do orçamento de raciocínio', async () => {
generateTextMock.mockResolvedValue({ text: 'Título curto' })
await deriveDemandTitle('pedido qualquer', 'material')
const call = generateTextMock.mock.calls[0]![0] as {
maxOutputTokens?: number
providerOptions?: unknown
}
expect(call.providerOptions).toEqual({ deepseek: { thinking: { type: 'disabled' } } })
expect(call.maxOutputTokens).toBeGreaterThanOrEqual(1000)
})
})