`src/backdrop-pick.ts` и `src/decor-image-editor.ts` не входили в
tsconfig.test.json — юнитов у них не было вовсе. Смок при этом подменял
`hass.callWS` целиком и до `uploadFromInput`, `upload`, `delete` не
доходил; в шапке файла это было честно написано. AC1 #51 обещал
доказательство «component unit + smoke» — не было ни того, ни другого.
Цена известна: #427 — файл тяжелее 2 МиБ нельзя было добавить ничем,
гасли обе кнопки диалога, включая «уменьшить копию», — прожил четыре
круга ревью именно потому, что этот путь не проверяло ничто.
Оба файла теперь в tsconfig.test.json (компиляция +6 с, без правок
продуктового кода) и покрыты 13 юнитами:
- классификация: проходной файл, тяжелее лимита источника (guard с
probe.kind='safe' — предупреждение о размере, не об отказе), warn,
hard, unknown, неподдерживаемый формат;
- состав кнопок диалога на трёх случаях. Декор свыше лимита: «Отмена» и
«уменьшить копию», без «оставить оригинал» — это и есть #427. Подложка
на том же файле сохраняет обе кнопки, hard остаётся с одной «Отмена»,
unknown предупреждает, а не проходит тихо;
- uploadFromInput: сброс input.value, молчание на занятом, отказ формата,
исключение классификации, передача флага замены в оба слота;
- upload: multipart-поле и URL, порядок каталога, палитра против замены
ссылки в диалоге, восемь ответов бэкенда с разными текстами, отпускание
busy на отказе, запрет второго запроса поверх незакончившегося;
- delete: ссылки на ассет, отказ в подтверждении, чистка каталога, карты
и палитры, различение in_use, сохранность каталога на отказе сервера;
- loadCatalog: отбор валидных строк и тост на отказе.
Смок `smoke_decor_images.mjs` получил последний блок, который проходит
настоящие uploadFromInput → upload → delete в собранном бандле, подменяя
только транспорт: fetchWithAuth и одну ветку callWS.
Свидетели (§2.7, #435). Девять мутаций прогнаны на собранном дереве,
каждая краснит свой тест: условие #427 → тест состава кнобок; снятие
лимита источника; input.value; флаг замены; too_large; busy в upload;
подтверждение удаления; used_by; проглоченный отказ каталога. Мутация
busy сначала вешала прогон и уносила пять тестов cancelledByParent —
тест переписан так, чтобы падать на сравнении, а не по таймауту.
В реестр добавлены три мутанта на продуктовый код: условие #427, потеря
флага замены, схлопывание кодов ошибок.
Гейты: npm test 1806 tests, 1805 pass, 0 fail (было 1791);
mutation-gate --check зелёный. Смок локально не прогнать — Chromium в
песочнице нет, проверит CI.
Issue: #433
User-Visible: no