У tradein-фронта не бежало ни одной проверки поведения: лэйн гейтил типы и
статический анализ, а оба молчат про то, что видит пользователь. Три компонента,
ломавшиеся за последние сутки, получают по проверке.
- SaleShareList: колонка «Дом» при пустой серии (#2700 — пусто у всех 9457 домов)
сверяется ЦЕЛИКОМ, потому что от «нарисовали дыру» отличает ровно хвостовой
разделитель, а подстрочное совпадение его не видит.
- StreetDealsCard + mapHistory: погашенный гейтом медианный торг (#2666/#2672)
показан объяснением, а не пустотой и не нулём. Мест показа два (карточка `/`
и HUD `/v2`), гейт один — проверяются оба.
- LoginPage: 429 (#2712/#2717) даёт своё сообщение. Подменяется fetch, а не
loginErrorMessage — работает настоящая apiFetch и настоящий HTTPError, то есть
проверяется путь от кода ответа до текста на экране. Рядом 401 и 500: без них
«429 показывает текст» прошло бы и на ветке, отвечающей одинаково на всё.
Каждая проверка проверена на слом: снят .filter(Boolean) → 4 красных; убран
блок median_discount_explanation и его половина note → 2 красных; удалена ветка
429 → 1 красный. Инфраструктура (vitest + jsdom + testing-library) скопирована
у frontend/, не изобретена. Шаг подключён в ci-tradein.yml после type-check.
Refs #2766