import { describe, it, expect } from 'vitest'; import { formatJudgeObjection, formatMentorObjection } from './objection-format.mjs'; describe('formatJudgeObjection', () => { it('склеивает дословные возражения (anchor.ref + severity)', () => { const v = { objections: [ { verdict: 'NO', anchor: { kind: 'failed_criterion', ref: 'шаг 3 не проверяемый исход' }, severity: 'heavy' }, ], slots: {} }; const s = formatJudgeObjection(v); expect(s).toContain('шаг 3 не проверяемый исход'); expect(s).toContain('heavy'); }); it('несколько возражений — все в выводе', () => { const v = { objections: [{ anchor: { ref: 'A' }, severity: 'fatal' }, { anchor: { ref: 'B' }, severity: 'light' }] }; const s = formatJudgeObjection(v); expect(s).toContain('A'); expect(s).toContain('B'); }); it('нет возражений → пустая строка', () => { expect(formatJudgeObjection({ objections: [], slots: {} })).toBe(''); }); it('мусорный вердикт не роняет', () => { expect(formatJudgeObjection(null)).toBe(''); expect(formatJudgeObjection({ objections: 'x' })).toBe(''); }); it('возражение без anchor.ref пропускается', () => { expect(formatJudgeObjection({ objections: [{ severity: 'heavy' }] })).toBe(''); }); it('читает блокирующие возражения судьи из поля blocking (форма runJudge, Фаза 1)', () => { const v = { decision: 'NO-GO', blocking: [{ verdict: 'NO', anchor: { kind: 'spec_section', ref: '§4 порог' }, severity: 'heavy' }], advice: [], slots: {} }; const s = formatJudgeObjection(v); expect(s).toContain('§4 порог'); expect(s).toContain('heavy'); }); }); describe('formatMentorObjection', () => { it('собирает дословный reason + суть вердикта (recommendation)', () => { const s = formatMentorObjection({ ok: false, wired: true, reason: 'шаг 2 склеен', verdict: { decision: 'NO-GO', recommendation: 'разбей шаг 2' } }); expect(s).toContain('шаг 2 склеен'); expect(s).toContain('разбей шаг 2'); }); it('ok=true → пустая строка (нет замечания)', () => { expect(formatMentorObjection({ ok: true, wired: true })).toBe(''); }); it('не wired → пустая строка ($0, наставник не судил)', () => { expect(formatMentorObjection({ ok: false, wired: false })).toBe(''); }); it('мусор не роняет', () => { expect(formatMentorObjection(null)).toBe(''); }); it('содержательный NO-GO → суть: recommendation + reasoning + пункты', () => { const r = { ok: true, wired: true, verdict: { decision: 'NO-GO', recommendation: 'добавь systematic-debugging', reasoning: 'это отладка бага', plan_points_addressed: ['шаг 2: скил не тот'] } }; const s = formatMentorObjection(r); expect(s).toMatch(/systematic-debugging/); expect(s).toMatch(/отладка бага/); expect(s).toMatch(/шаг 2/); }); it('GO → пустая строка (не заворот)', () => { expect(formatMentorObjection({ ok: true, wired: true, verdict: { decision: 'GO' } })).toBe(''); }); });