// Mistral provider — unit tests // Uses Node.js built-in test runner (node:test) — no extra dependencies import { describe, it, mock, beforeEach } from 'node:test'; import assert from 'node:assert/strict'; import { MistralProvider } from '../lib/llm/mistral.mjs'; import { createLLMProvider } from '../lib/llm/index.mjs'; // ─── Unit Tests ─── describe('MistralProvider', () => { it('should set defaults correctly', () => { const provider = new MistralProvider({ apiKey: 'sk-test' }); assert.equal(provider.name, 'mistral'); assert.equal(provider.model, 'mistral-large-latest'); assert.equal(provider.isConfigured, true); }); it('should accept custom model', () => { const provider = new MistralProvider({ apiKey: 'sk-test', model: 'mistral-small-2603' }); assert.equal(provider.model, 'mistral-small-2603'); }); it('should report not configured without API key', () => { const provider = new MistralProvider({}); assert.equal(provider.isConfigured, false); }); it('should throw on API error', async () => { const provider = new MistralProvider({ apiKey: 'sk-test' }); const originalFetch = globalThis.fetch; globalThis.fetch = mock.fn(() => Promise.resolve({ ok: false, status: 401, text: () => Promise.resolve('Unauthorized') }) ); try { await assert.rejects( () => provider.complete('system', 'user'), (err) => { assert.match(err.message, /Mistral API 401/); return true; } ); } finally { globalThis.fetch = originalFetch; } }); it('should parse successful response', async () => { const provider = new MistralProvider({ apiKey: 'sk-test' }); const mockResponse = { choices: [{ message: { content: 'Hello from Mistral' } }], usage: { prompt_tokens: 10, completion_tokens: 5 }, model: 'mistral-large-latest', }; const originalFetch = globalThis.fetch; globalThis.fetch = mock.fn(() => Promise.resolve({ ok: true, json: () => Promise.resolve(mockResponse) }) ); try { const result = await provider.complete('You are helpful.', 'Say hello'); assert.equal(result.text, 'Hello from Mistral'); assert.equal(result.usage.inputTokens, 10); assert.equal(result.usage.outputTokens, 5); assert.equal(result.model, 'mistral-large-latest'); } finally { globalThis.fetch = originalFetch; } }); it('should send correct request format', async () => { const provider = new MistralProvider({ apiKey: 'sk-test-key', model: 'mistral-large-latest' }); let capturedUrl, capturedOpts; const originalFetch = globalThis.fetch; globalThis.fetch = mock.fn((url, opts) => { capturedUrl = url; capturedOpts = opts; return Promise.resolve({ ok: true, json: () => Promise.resolve({ choices: [{ message: { content: 'ok' } }], usage: { prompt_tokens: 1, completion_tokens: 1 }, model: 'mistral-large-latest', }), }); }); try { await provider.complete('system prompt', 'user message', { maxTokens: 2048 }); assert.equal(capturedUrl, 'https://api.mistral.ai/v1/chat/completions'); assert.equal(capturedOpts.method, 'POST'); const headers = capturedOpts.headers; assert.equal(headers['Content-Type'], 'application/json'); assert.equal(headers['Authorization'], 'Bearer sk-test-key'); const body = JSON.parse(capturedOpts.body); assert.equal(body.model, 'mistral-large-latest'); assert.equal(body.max_tokens, 2048); assert.equal(body.messages[0].role, 'system'); assert.equal(body.messages[0].content, 'system prompt'); assert.equal(body.messages[1].role, 'user'); assert.equal(body.messages[1].content, 'user message'); } finally { globalThis.fetch = originalFetch; } }); it('should handle empty response gracefully', async () => { const provider = new MistralProvider({ apiKey: 'sk-test' }); const originalFetch = globalThis.fetch; globalThis.fetch = mock.fn(() => Promise.resolve({ ok: true, json: () => Promise.resolve({ choices: [], usage: {} }), }) ); try { const result = await provider.complete('sys', 'user'); assert.equal(result.text, ''); assert.equal(result.usage.inputTokens, 0); assert.equal(result.usage.outputTokens, 0); } finally { globalThis.fetch = originalFetch; } }); }); // ─── Factory Tests ─── describe('createLLMProvider — mistral', () => { it('should create MistralProvider for provider=mistral', () => { const provider = createLLMProvider({ provider: 'mistral', apiKey: 'sk-test', model: null }); assert.ok(provider instanceof MistralProvider); assert.equal(provider.name, 'mistral'); assert.equal(provider.isConfigured, true); }); it('should be case-insensitive', () => { const provider = createLLMProvider({ provider: 'Mistral', apiKey: 'sk-test', model: null }); assert.ok(provider instanceof MistralProvider); }); it('should return null for empty provider', () => { const provider = createLLMProvider({ provider: null, apiKey: 'sk-test', model: null }); assert.equal(provider, null); }); });