397777089e
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
58 lines
3.2 KiB
JavaScript
58 lines
3.2 KiB
JavaScript
import { describe, it, expect } from 'vitest';
|
||
import { buildEmergePrompt, validateEmergeTrace, runEmergeCheck } from './router-emerge.mjs';
|
||
|
||
describe('buildEmergePrompt (чистая {system,user}; узкий — только последний ответ + план)', () => {
|
||
const base = { lastAnswer: 'и сделай отступ побольше', plan: 'план: правлю роутер' };
|
||
it('детерминирована', () => {
|
||
expect(buildEmergePrompt(base).system).toBe(buildEmergePrompt(base).system);
|
||
expect(buildEmergePrompt(base).user).toBe(buildEmergePrompt(base).user);
|
||
});
|
||
it('system: «только этот ответ», не весь пересчёт; user несёт последний ответ + план', () => {
|
||
const { system, user } = buildEmergePrompt(base);
|
||
expect(system).toMatch(/только.*последн|узк/i);
|
||
expect(system).toMatch(/НЕ пересчитывай|не пересчит/i);
|
||
expect(user).toMatch(/сделай отступ побольше/);
|
||
expect(user).toMatch(/план: правлю роутер/);
|
||
});
|
||
});
|
||
|
||
describe('validateEmergeTrace (форма: emerged массив; пункт {item непустой})', () => {
|
||
it('корректный (с нуждой) → ok', () => {
|
||
expect(validateEmergeTrace({ emerged: [{ item: 'отступ', detail: 'мобильный поедет' }] }).ok).toBe(true);
|
||
});
|
||
it('пустой emerged → ok (ничего нового — норм)', () => {
|
||
expect(validateEmergeTrace({ emerged: [] }).ok).toBe(true);
|
||
});
|
||
it('нет массива emerged → не ok', () => {
|
||
expect(validateEmergeTrace({}).ok).toBe(false);
|
||
});
|
||
it('пункт без item → badItems', () => {
|
||
const r = validateEmergeTrace({ emerged: [{ detail: 'x' }] });
|
||
expect(r.ok).toBe(false); expect(r.badItems).toContain('emerged[0]');
|
||
});
|
||
});
|
||
|
||
describe('runEmergeCheck (оркестратор; llmCall мокается; hasEmerged кодом)', () => {
|
||
const base = { lastAnswer: 'сделай отступ', plan: 'p' };
|
||
it('нашёл нужду → ok + hasEmerged true', async () => {
|
||
const r = await runEmergeCheck({ ...base, llmCall: async () => ({ emerged: [{ item: 'отступ' }] }) });
|
||
expect(r.ok).toBe(true); expect(r.hasEmerged).toBe(true); expect(r.emerged.length).toBe(1);
|
||
});
|
||
it('ничего нового → ok + hasEmerged false', async () => {
|
||
const r = await runEmergeCheck({ ...base, llmCall: async () => ({ emerged: [] }) });
|
||
expect(r.ok).toBe(true); expect(r.hasEmerged).toBe(false);
|
||
});
|
||
it('строка с JSON-fence → парсится (DRY)', async () => {
|
||
const r = await runEmergeCheck({ ...base, llmCall: async () => '```json\n{"emerged":[]}\n```' });
|
||
expect(r.ok).toBe(true); expect(r.hasEmerged).toBe(false);
|
||
});
|
||
it('мусор → ok=false', async () => {
|
||
const r = await runEmergeCheck({ ...base, llmCall: async () => null });
|
||
expect(r.ok).toBe(false);
|
||
});
|
||
it('исключение → ok=false, reason про сбой', async () => {
|
||
const r = await runEmergeCheck({ ...base, llmCall: async () => { throw new Error('net'); } });
|
||
expect(r.ok).toBe(false); expect(r.reason).toMatch(/сбой|модел/i);
|
||
});
|
||
});
|