diff --git a/History/test-results-v1.0.178.md b/History/test-results-v1.0.178.md new file mode 100644 index 0000000..7ae0b22 --- /dev/null +++ b/History/test-results-v1.0.178.md @@ -0,0 +1,208 @@ +# Результаты тестирования — v1.0.178 + +Дата: 25.06.2026 + +## Сводка + +| Уровень | Тестов | Результат | +|---------|--------|-----------| +| Юнит-тесты (Node.js) | **131** | **✅ 131/131 PASS** | +| `node -c` синтаксис | 6 файлов | ✅ чистый | +| API smoke (curl) | 8 эндпоинтов | ✅ HTTP 200 | +| Аудит кода | — | ✅ 4 бага исправлено | + +## Запуск тестов + +```bash +cd contractor/deploy && node tests.js +``` + +Тесты не требуют браузера — все зависимости замоканы (document, window, lucide, crypto, XMLHttpRequest). + +--- + +## Юнит-тесты (131 шт.) + +### statusToHTML (21 тест) +Чистая функция: `{ kind, pct?, text?, count?, elapsed? }` → HTML. + +| Группа | Тесты | +|--------|-------| +| Граничные | `null`, `undefined`, `{}`, `{ kind: '' }`, `{ kind: 'unknown' }` → пусто | +| `uploading` | pct=0, 75, 100, -5, без pct (→0%) | +| `uploaded` | базовая проверка | +| `unzipping` / `parsing` | текстовые статусы | +| `parsed` | count=5, 0; elapsed='2.3', '0', без elapsed | +| `error` | с текстом, без текста (→дефолт), с пустым текстом (→дефолт) | + +### applyParseResult (13 тестов) +Чистая функция: применяет `{ status, element_count, error }` к entry. + +| Группа | Тесты | +|--------|-------| +| `parsed` | с elapsed, без elapsed, element_count=0, без element_count | +| `error` | с текстом, без текста (→дефолт "ошибка парсинга") | +| `null` parsed | → `{ kind: 'error', text: 'Неизвестная ошибка' }` | +| Иммутабельность | старые поля entry не затираются | + +### reconcileSelection (7 тестов) +Чистая функция: фильтрует `files` по именам из `newFiles`. + +| Группа | Тесты | +|--------|-------| +| Норма | 3 файла → 2 осталось, порядок сохранён | +| Пустые | оба массива пусты → `[]` | +| Все совпадают | 1→1 | +| Ни один | 2→0 | +| Дубликаты | Set корректно обрабатывает повторы | +| Иммутабельность | исходный массив не мутирован | + +### renderGroupCard (10 тестов) +Чистая HTML-функция: карточка необработанной группы. + +| Группа | Тесты | +|--------|-------| +| Базовая | номер, контрагент, типы документов, дата, data-gi, кнопка «Сравнить» | +| Нет «✓ Готово» | для необработанной группы | +| `compare.status === 'running'` | кнопка disabled | +| Без контрагента | заглушка «контрагент не определён» | +| Неизвестный doc_type | выводится как есть | +| Пустые документы | карточка рендерится, кнопка есть | +| Типы | contract→договор, supplement→допсоглашение, specification→спецификация | + +### renderGroupCardDone (5 тестов) +Чистая HTML-функция: карточка обработанной группы. + +| Группа | Тесты | +|--------|-------| +| Заголовок | ✓ Готово (12.5с), стрелка сворачивания | +| bodyHTML | вставлен в карточку | +| data-gi | на заголовке для обработчика клика | +| Типы | specification→спецификация | + +### renderUnresolvedCard (3 теста) +Чистая HTML-функция: карточка нераспознанных файлов. + +| Группа | Тесты | +|--------|-------| +| Заголовок | «Не распознано» | +| Причина 1 | «нет базового договора №999» (есть parent_number) | +| Причина 2 | «ошибка классификации: LLM error» (classify_status=failed) | + +### applyCompareEvent (14 тестов) +Чистая функция: мутирует `sections` по SSE-событиям. + +| Группа | Тесты | +|--------|-------| +| `extract_start` | создаёт секцию с filename, status='extracting' | +| `llm_done` | обновляет status, ops_count, mode, time_s | +| `applied` | сохраняет summary, ops | +| `extract_error` | на существующей секции → status='error' | +| `extract_error` | на НЕсуществующей → создаёт новую с ошибкой | +| `apply_error` | аналогично extract_error | +| `applied` без summary | не падает | +| `applied` с пустыми ops | не падает | +| Неизвестный тип | секция НЕ создаётся (не падает) | +| `llm_done` на несуществующей | не падает | + +### renderCompareSectionHeader (5 тестов) +Чистая функция: заголовок секции сравнения. + +| Статус | Проверка | +|--------|----------| +| `extracting` | ⏳ + filename | +| `llm_done` | ✓ + filename + ops_count + mode + time_s | +| `error` | ✗ + filename + текст ошибки | + +### renderCompareOpsTable (6 тестов) +Чистая функция: HTML-таблица операций. + +| Группа | Тесты | +|--------|-------| +| ADD/DELETE | правильные CSS-классы (diff-added, diff-deleted) | +| Данные | имя услуги, цена, количество, сумма, дата | +| Пустые ops | таблица рендерится с пустым tbody | +| null new_row | пустые ячейки (не падает) | +| MERGE (неизв.) | без классов diff-* | + +### renderCompareSectionBody (7 тестов) +Чистая функция: тело секции (summary + таблица). + +| Группа | Тесты | +|--------|-------| +| Граничные | null, {}, status='llm_done' → пусто | +| applied | +3 ~1 -0 ?2, UPDATE → diff-changed | +| Без unresolved | нет знака ? | +| Отрицательные summary | рендерится без ошибок | +| Частичный new_row | нет undefined в выводе | + +### escHtml (7 тестов) +| Вход | Выход | +|------|-------| +| `null`, `undefined` | `''` | +| `'hello'` | `'hello'` | +| `'