Files
brain/tools/secretary-render-fluffy.test.mjs
T

82 lines
4.9 KiB
JavaScript

import { describe, it, expect } from 'vitest';
import { renderFluffy, renderDoc } from './secretary-render-fluffy.mjs';
const base = () => ({ subject: 'дело', status: 'открыто', decisions: [], will: [], open: [], consequences: [], doneNext: [], hidden: [], acceptance: [], tails: [], candidates: [], steps: [] });
describe('renderFluffy', () => {
it('пустой протокол не падает, даёт заголовок и секции', () => {
const md = renderFluffy(base());
expect(md).toContain('# 📋 Протокол: дело');
expect(md).toContain('## 🌳 Ствол');
expect(md).toContain('## 🧭 Шаги');
});
it('живое решение наверху, зачёркнутое — в свёрнутом блоке, оба со ссылкой', () => {
const p = base();
p.decisions = [{ text: 'живое', why: 'потому', struck: false, turns: [5] }, { text: 'старое', struck: true, turns: [3] }];
const md = renderFluffy(p);
expect(md).toMatch(/- живое — потому.*ходы\/turn-5\.log/);
expect(md).toContain('<details><summary>▸ решённое в стволе');
expect(md).toMatch(/~~старое~~.*ходы\/turn-3\.log/);
});
it('ёлочка: ветки+кандидаты по теме, важное для владельца сверху, 🔴/⚪', () => {
const p = base();
p.hidden = [{ id: 'СВ-1', тема: 'поиск', важность: 'high', title: 'дыра поиска', status: 'открыт', born: 1 }];
p.candidates = [
{ id: 'КД-1', тема: 'поиск', важность: 'low', title: 'мелочь поиска', branch: 'b', status: 'жив', born: 1 },
{ id: 'КД-2', тема: 'тесты', важность: 'high', gap: true, title: 'нет тестов', branch: 'b', status: 'жив', born: 1 },
];
const md = renderFluffy(p);
expect(md).toContain('## 🌳 Темы');
expect(md).toMatch(/📂 поиск/);
expect(md).toContain('🔴');
expect(md.indexOf('дыра поиска')).toBeLessThan(md.indexOf('мелочь поиска')); // важное выше в теме
});
it('пробел-пласт помечен ⚠️ ПРОБЕЛ-ПЛАСТ', () => {
const p = base();
p.candidates = [{ id: 'КД-2', тема: 'тесты', важность: 'high', gap: true, title: 'нет тестов', branch: 'b', status: 'жив', born: 1 }];
expect(renderFluffy(p)).toMatch(/ПРОБЕЛ-ПЛАСТ/);
});
it('мёртвые (отпал/закрыт) НЕ показаны в пульте (они в архиве)', () => {
const p = base();
p.candidates = [{ id: 'КД-3', тема: 'x', status: 'отпал', title: 'мертвец-кандидат', branch: 'b', born: 1 }];
p.hidden = [{ id: 'СВ-9', тема: 'x', status: 'закрыт', title: 'мертвец-ветка', born: 1 }];
expect(renderFluffy(p)).not.toMatch(/мертвец/);
});
it('горящие Л8/Л9 показаны с источником', () => {
const p = base();
p.acceptance = [{ text: 'не проверено', born: 3, done: false }];
p.tails = [{ text: 'не убрано', born: 3, done: false }];
const md = renderFluffy(p);
expect(md).toContain('## 🔥 Горит');
expect(md).toMatch(/Приёмка \(Л8\):.*не проверено.*turn-3\.log/);
expect(md).toMatch(/Хвост \(Л9\):.*не убрано/);
});
it('шаги со ссылкой на файл хода', () => {
const p = base();
p.steps = [{ turn: 15, text: 'Ход 15 — я: …' }];
const md = renderFluffy(p);
expect(md).toMatch(/- \[Ход 15\]\(ходы\/turn-15\.log\) — Ход 15/);
});
});
describe('renderDoc — развилка по флагу', () => {
const proto = { subject: 'дело', status: 'открыто', decisions: [{ text: 'A', struck: false }], will: [], open: [], consequences: [], doneNext: [], hidden: [], acceptance: [], tails: [], candidates: [], steps: [] };
it('флаг ON → пушистый рендер (🌳 Ствол)', () => {
expect(renderDoc(proto, {}, { SECRETARY_FLUFFY: '1' })).toContain('## 🌳 Ствол');
});
it('флаг OFF (по умолчанию) → старый renderProtocol (## Решения, без 🌳)', () => {
const md = renderDoc(proto, {}, {});
expect(md).toContain('## Решения');
expect(md).not.toContain('🌳');
});
});
describe('renderFluffy — база знаний', () => {
it('печатает раздел между темой и стволом', () => {
const md = renderFluffy({ ...base(), subject: 'тема', knowledge: [{ ref: 'f.mjs:10', text: 'факт' }] });
expect(md).toContain('## 🧠 База знаний');
expect(md).toContain('факт — f.mjs:10');
expect(md.indexOf('База знаний')).toBeLessThan(md.indexOf('🌳 Ствол'));
});
});