33 lines
1.4 KiB
JavaScript
33 lines
1.4 KiB
JavaScript
import test from 'node:test';
|
||
import assert from 'node:assert';
|
||
import { safeImport } from '../_helpers/path.js';
|
||
import { MockLLMManager } from '../_helpers/mockLLMManager.js';
|
||
|
||
test('LLM transient error is retried or bubbled cleanly', async () => {
|
||
const mgrRes = safeImport('LLMManager');
|
||
if (!mgrRes.ok || typeof mgrRes.mod.callModel !== 'function') {
|
||
console.warn('[SKIP] LLMManager.callModel missing');
|
||
return;
|
||
}
|
||
// On teste la nôtre (mock) pour vérifier le comportement désiré,
|
||
// puis on appelle la “vraie” et on vérifie au moins la remontée d’erreur propre.
|
||
const mock = new MockLLMManager({ failTimes: 2, failCode: 429 });
|
||
const ok = await mock.callModel({ input:'test' }).catch(e => e);
|
||
// après 2 fails, la troisième doit passer:
|
||
const ok2 = await mock.callModel({ input:'test 2' });
|
||
assert.ok(ok2.completion?.startsWith('MOCK'));
|
||
|
||
// Vraie impl: au minimum, qu’elle throw une Error avec statusCode si pas de retry
|
||
let threw = false;
|
||
try {
|
||
await mgrRes.mod.callModel({ provider:'X', model:'Y', input:'Z', __forceFail429:true });
|
||
} catch (e) {
|
||
threw = true;
|
||
// Pas obligatoire d’avoir statusCode, mais on log si présent
|
||
if (e?.statusCode) {
|
||
assert.ok([429,500,502,503,504].includes(e.statusCode));
|
||
}
|
||
}
|
||
assert.ok(threw, 'real callModel should throw or handle gracefully when forced to fail');
|
||
});
|