Перейти к основному содержимому

Как тестировать, когда платы нет

Плата физически отключена и недоступна. Всё, что осталось от живого железа, — это байты в packages/lock-protocol/test/vectors.ts и описание протокола. Поэтому у проекта две опоры: векторы и эмулятор платы.

Векторы — неприкосновенны

Векторы сгенерированы из съёма живого устройства и руками не правятся.

Падающий тест на векторах — это не «поправить тест»

Если тест на векторах упал, значит код разошёлся с поведением железа. Правильное действие — вернуть код как было, а не подогнать ожидание. Проверить, кто прав, уже негде: платы нет.

Запуск:

npm test # весь репозиторий
npm run test:watch

Чем что покрыто на 2026-09-01 (числа быстро растут — смотрите вывод, а не таблицу):

ПакетТестыО чём они
lock-protocolвекторы с живого железакадры, контрольная сумма, разбор потока, барьер запрещённых кадров
contracts123схемы обмена: что примут и что отвергнут
i18n80полнота словарей и длина строк под экран 800 × 1280
panel200состояния ячеек, журнал, тревоги, привязка, опознание звонящего

⚠️ Сквозные тесты панели (Playwright) написаны, но ни разу не запускались — так и помечено в apps/panel/README.md. Считать их зелёными нельзя.

Эмулятор платы — packages/lock-sim

Это не игрушка, а единственное место, где поведение платы теперь существует. Правится он не «как удобнее», а только следом за документом протокола и векторами.

ФайлЧто внутри
board.tsмодель платы: 27 каналов, импульс 357 мс, эхо на открытие, тишина на битую сумму
faults.tsрежимы неисправности — ради них модель и нужна
transport.tsLockTransport — то, через что приложение говорит с платой, одинаково с моделью и с нативным портом
cli.tsзапуск моделью отдельным процессом (--stdio, --pty)

Что модель воспроизводит намеренно неудобно

Эти решения выглядят странно, и «чинить» их нельзя — они и есть смысл эмулятора:

  • На кадр с несошедшейся контрольной суммой модель не отвечает вообще. Не ошибку, не отказ — тишину. Так вела себя плата. Приложение обязано уметь ждать впустую.
  • Команды «закрыть» нет. «Закрыто» появляется только оттого, что дверцу закрыли, или по таймеру автозакрытия — и никогда от команды по линии.
  • Открытие подтверждается эхом, и это «команда принята», а не «дверь открылась». Дверь отходит через импульс в 357 мс, и модель честно держит эту паузу. Код, который считает подтверждение доказательством открытия, обязан на этом падать — иначе он упадёт на шкафу.
  • Неподключённый канал отвечает ровно как открытая дверь. Различить их по линии нельзя, и модель такой возможности не даёт намеренно.
  • Запрещённые кадры модель не исполняет, молчит в ответ и громко записывает попытку. Лучше поймать это на ноутбуке, чем на шкафу.

Часы

Модель не заводит таймеров: время приходит снаружи, а переходы «импульс дотолкнул дверь» и «человек закрыл» применяются лениво, при первом обращении после наступления срока. Поэтому тесты мгновенные и детерминированные, а транспорт при желании подставляет настоящие часы.

Неисправности, которые стоит гонять

Исправная плата в тестах почти ничего не доказывает. Проверять надо то, что случается на полудуплексной линии в уличном шкафу: мусор в приёмнике при переключении направления, разорванный на части кадр, ответ, пришедший слишком поздно, застрявший канал, порча отдельных байтов. Набор режимов — в faults.ts, конкретные имена смотрите там: пакет пишется прямо сейчас.

Чего эмулятор не проверит никогда

Список короткий и важный — здесь заканчивается зона, где «зелёные тесты» что-то значат:

  • реальный датчик двери — есть ли он на канале, жив ли шлейф;
  • физику импульса — что катушка действительно втянула язычок;
  • питание — просадки при одновременных щелчках;
  • сканер — его на плате не было вообще;
  • сторожевой таймер — его поведение проверяется только аптаймом на живой плате.

Правило проекта: зелёные моки ничего не доказывают. Всё, что не покрыто векторами с живого железа, — гипотеза до первой проверки на шкафу.

Ручная проверка обмена

Пока плата была жива, протокол снимали инженерным экраном киоска: скрытый вход — пять касаний правого верхнего угла за три секунды. Экран умеет открыть порт, послать открытие, чтение или произвольные байты и показать лог обмена с разбором кадров. Он остаётся на месте и пригодится при первом же подключении собранного шкафа.