233 lines
21 KiB
Markdown
233 lines
21 KiB
Markdown
# Проверки площадки для разработчика
|
||
|
||
Для работы площадки эти файлы не нужны. Обычный запуск: `make venue`.
|
||
|
||
- `deploy.py` — запускает проверки единого HTTPS-деплоя из `https.py` без Docker:
|
||
первый запуск, повторная сборка Docker-образа, принудительный перезапуск,
|
||
отсутствие артефактов, сертификаты и сохранность настроек.
|
||
- `smoke.py` — проверяет работающую площадку через API. Без `--verify` создаёт
|
||
тестовые данные; с `--verify` проверяет ранее созданные данные. Всегда
|
||
использует HTTPS и прежние домены с проверкой доверия TLS; требует локального DNS.
|
||
- `https.py` — проверяет сертификаты и HTTPS-запуск с подставными командами.
|
||
`--docker` дополнительно запускает два временных Nginx-контейнера в отдельной
|
||
сети, проверяет TLS, маршруты, перенаправления и перезапуск, затем удаляет
|
||
свои контейнеры и сеть. Использует локальный `nginx:alpine` и временный тестовый CA;
|
||
работающие окружения, production и системное хранилище доверия не меняет.
|
||
- `dns.py --docker` — проверяет оба локальных домена по UDP/TCP и отсутствие
|
||
внешних IPv6-ответов в отдельной внутренней Docker-сети без WAN до и после
|
||
перезапуска CoreDNS. `--server <IP ноутбука>` проверяет работающий DNS.
|
||
|
||
Команды из корня проекта:
|
||
|
||
```sh
|
||
python3 tests/venue/deploy.py
|
||
python3 tests/venue/smoke.py --verify
|
||
python3 tests/venue/https.py
|
||
python3 tests/venue/https.py --docker
|
||
python3 tests/venue/dns.py --docker
|
||
python3 tests/venue/dns.py --server 192.168.10.155
|
||
```
|
||
|
||
## Полный flow ED-029, этап 8
|
||
|
||
```sh
|
||
python3 tests/venue/flow.py
|
||
python3 tests/venue/flow.py --browser
|
||
python3 tests/venue/flow.py --results
|
||
python3 tests/venue/flow.py --apply
|
||
python3 tests/venue/flow.py --apply --browser
|
||
```
|
||
|
||
`flow.py` собирает актуальный Go/Vue-код во временном каталоге, поднимает
|
||
одноразовые prod/venue-серверы с отдельными PostgreSQL и RustFS в Docker-сети
|
||
`--internal`, затем удаляет только свои контейнеры, тома и сеть. Работающие
|
||
окружения, файлы `prod`/`venue`, их настройки и Cudy не меняются. Требуются
|
||
установленные Go, Node/npm, frontend-зависимости и доступ к Docker; образы
|
||
`postgres:15`, `rustfs/rustfs:latest` и `alpine:3.22` должны быть доступны локально
|
||
(скрипт использует `--pull=never`). SMTP источника направлен в локальный sink,
|
||
который закрывает соединение; успешная отправка писем не проверяется.
|
||
|
||
Проверяются оба формата (`offline` и `online`): экспорт и импорт настоящего ZIP,
|
||
исходные ссылки команд/билетов, статусы участия, QR/PDF, приём билетов и его
|
||
конкурентность, новые локальные команды/билеты, ходы и материалы, запрет ходов
|
||
до старта/на паузе/после завершения, перезапуск всех venue-сервисов, ответы,
|
||
оценивание, результаты и повторный импорт без потери прогресса. Дополнительно
|
||
запускается полный Go-набор с PostgreSQL, включая gameplay/lifecycle, tickets, MCP и app. Выдача
|
||
токенов писем имитируется только в тестовой БД; решения капитанов выполняются
|
||
через штатный API. Возврат результатов на источник не выполняется.
|
||
|
||
`--browser` требует Firefox с Marionette и запускает отдельный чистый стенд.
|
||
Реальные интерфейсы проходят экспорт, скачивание, загрузку ZIP, проверку билета,
|
||
ходы, выдачу материала, оценивание и завершение на 1440 px (`online`) и 390 px
|
||
(`offline`). Проверяются клавиатурный focus, отказ на ход с сохранением ввода,
|
||
блокировка повторной отправки и кнопки на паузе при уже введённом коде.
|
||
Локальный HTTP-прокси переключает один публичный адрес между двумя реальными
|
||
backend, имитируя смену DNS; Игровые API-ответы не подменяются; ошибки, пустой список и состояния Wi-Fi
|
||
панели мониторинга дополнительно проверяются управляемыми ответами GetDevices. Тестовые ссылки, ZIP,
|
||
профиль Firefox и сборки остаются во временном каталоге до конца прогона.
|
||
|
||
`--results` дополнительно проверяет этап 9: серверный сервис собирает ZIP
|
||
результатов обеих завершённых игр из реальной тестовой БД. Проверяются привязка
|
||
к исходному ZIP, прогресс/материалы/баллы, новый снимок после оценивания,
|
||
конкурентное оценивание, сохранность предыдущего пакета, повтор после
|
||
перезапуска и отсутствие изменений исходных игр. Локальные ссылки RustFS
|
||
в пакеты не попадают. ZIP находятся только во временном каталоге с правами
|
||
0600; новые API/UI для возврата и применение онлайн не выполняются.
|
||
|
||
### Ручная контрольная точка этапа 8
|
||
|
||
Автоматический прогон не заменяет проверку телефонов и камеры. После отдельного
|
||
обновления реальной площадки актуальными артефактами, только на тестовой игре:
|
||
|
||
1. На источнике подготовить пакет с заранее выданными билетами и QR команд;
|
||
скачать и импортировать его на venue через интерфейс.
|
||
2. Отключить WAN и мобильные данные. На Android/iPhone открыть прежние ссылки
|
||
билета и команды через Wi-Fi площадки, проверить доверенный HTTPS.
|
||
3. Проверить билет у организатора и принять его; повтор должен показывать
|
||
использованный билет. Проверить QR камерой там, где браузер поддерживает
|
||
сканирование; при отсутствии поддержки проверить ручную вставку ссылки.
|
||
4. Начать игру, выполнить ход, выдать материал, поставить на паузу с введённым
|
||
следующим кодом: ход должен блокироваться. Продолжить и выполнить этот ход.
|
||
5. Проверить правила формата: в `offline` материалы выдаёт организатор и нет
|
||
цифровых ответов; в `online` игрок сохраняет ответ. Завершить игру, выставить
|
||
баллы и открыть результаты; игрок должен увидеть сообщение о завершении.
|
||
6. Повторить импорт исходного ZIP: билеты и локальный прогресс должны сохраниться.
|
||
Сообщить результат этой контрольной точки для приёмки этапа 8.
|
||
|
||
Нагрузка на 100 клиентов, покрытие Wi-Fi, ZIP на 1 ГиБ и возврат результатов
|
||
относятся к отдельным проверкам/этапам. До готовности возврата использовать
|
||
только тестовые игры.
|
||
|
||
|
||
`--apply` включает проверки этапа 9 и дополнительно проверяет этап 10:
|
||
настоящий ZIP площадки применяется серверным сервисом к изолированному prod,
|
||
с проверкой исходного ZIP в private RustFS. Проверяются перезапись онлайн-правок данными ZIP,
|
||
сохранение онлайн-оформления, исправленный балл,
|
||
повтор старого ZIP после нового и после перезапуска prod, прежние QR/билеты и
|
||
ссылки новых venue-команд/билетов, исчезновение `game.export`. Новых endpoint-ов
|
||
нет: service-only Go harness вызывается из стенда. Все ZIP и ресурсы остаются
|
||
в приватном временном каталоге и удаляются после прогона.
|
||
|
||
|
||
Этап 11: `--browser` также проходит возврат обоих форматов через реальные
|
||
интерфейсы: свежий ZIP кнопкой venue, загрузка на странице prod, предупреждение
|
||
о перезаписи, блокировка повторного запроса, результаты, старые ссылки/билеты,
|
||
сохранение названия/описания, исчезновение офлайн-отметки, исправленная оценка,
|
||
перезапись онлайн-ответа и повтор старого пакета после перезапуска. Прокси стенда
|
||
проверяет лимит ZIP 1 ГиБ и использует таймаут 30 минут; небольшая задержка
|
||
ответа применяется только для проверки блокировки кнопки. До пользовательских
|
||
flow запускаются PostgreSQL/race-регрессии возврата и реального HTTP-применения.
|
||
Работающие серверы не меняются; фактическая загрузка ZIP 1 ГиБ не проверяется.
|
||
|
||
### Учёт устройств (этап 12)
|
||
|
||
`python3 tests/venue/flow.py --browser` проверяет реальный публичный heartbeat,
|
||
права чтения, prod/venue, UUID и сочетания полей, неверные credentials,
|
||
отменённое участие, смену/очистку контекста, фильтр игры и отсутствие секретов.
|
||
Firefox проверяет игрока, организатора и экран в отдельных вкладках одного
|
||
профиля, привязку экрана, SPA-навигацию, новые подключения при перезагрузке,
|
||
остановку heartbeat, восстановление сети и повторную регистрацию через
|
||
интервал после перезапуска backend. Прогон изолирован от работающих серверов.
|
||
|
||
Границы 60 секунд/15 минут, лимит 1024, конкурентное чтение/обновление и
|
||
безопасное ограничение User-Agent проверяются тестами сервиса с управляемыми
|
||
часами (`go test -race ./internal/services/device_presence_service ./internal/app`).
|
||
Фронтенд self-check: `node src/utils/__tests__/deviceID.test.ts`,
|
||
`node src/stores/__tests__/devicePresence.test.ts` и
|
||
`node src/composables/__tests__/devicePresence.test.ts`: временный UUID,
|
||
отозванные lifecycle-контексты, отсутствие параллельных heartbeat,
|
||
остановка после `enabled=false`, повтор ошибок по интервалу и независимость
|
||
публичных credentials от JWT. Нагрузочный и аппаратный прогоны не включены.
|
||
|
||
|
||
### Панель состояния (этап 13)
|
||
|
||
`python3 tests/venue/flow.py --browser` дополнительно проверяет Firefox:
|
||
сводку и серверное время, встроенную ошибку с сохранением снимка, повтор,
|
||
пустой список, остановку запросов после переключения вкладки; отдельного
|
||
разработчика в venue/prod, безопасный состав GetGame/GetGames, скрытые создание
|
||
и результаты, нормализацию `tab=answers` в `state`, единственную вкладку и
|
||
обычный браузерный heartbeat. Проверки нескольких вкладок и смены контекста
|
||
этапа 12 остаются частью прогона. Потеря API и пустой ответ воспроизводятся
|
||
перехватом только GetDevices в браузере; остальные API реальные.
|
||
|
||
`node src/composables/__tests__/gameState.test.ts` (из frontend) проверяет
|
||
счётчики, сортировку, отсутствие параллельных запросов, активность вкладки,
|
||
ошибку/восстановление и отбрасывание ответов после смены игры, ухода и unmount.
|
||
Временные границы connected остаются в тестах сервиса этапа 12 с управляемыми
|
||
часами; клиент пороги не пересчитывает.
|
||
|
||
|
||
## Wi-Fi и нагрузка (этапы 14–15)
|
||
|
||
```sh
|
||
python3 tests/venue/load.py
|
||
python3 tests/venue/flow.py --apply --browser
|
||
```
|
||
|
||
`load.py` использует тот же одноразовый стенд без WAN: 100 виртуальных UUID,
|
||
25 новых команд по четыре браузера, 60 секунд. Каждый профиль отправляет
|
||
heartbeat раз в 20 секунд и читает историю раз в 5 секунд; по одному профилю
|
||
команды выполняют два хода и сохраняют ответ. Организатор опрашивает состояние
|
||
раз в 5 секунд. Проверяются ровно 100 доступных устройств, 50 сохранённых ходов,
|
||
25 ответивших команд и отсутствие HTTP-ошибок. Отчёт содержит число запросов,
|
||
p50/p95/max; p95 ≤ 2 секунды — бюджет этого теста, не обещание для любого железа.
|
||
Запросы идут прямо к backend по HTTP: DNS, HTTPS и прокси проверяются отдельно
|
||
`dns.py --docker` и `https.py --docker`. Это нагрузка backend, не проверка радио.
|
||
|
||
Go-тесты адаптера Cudy проверяют вход/продление сессии, ограничение URL/ответа,
|
||
разбор обеих полос, отсутствующий сигнал, ошибку при неизвестной разметке,
|
||
атомарный снимок, свежесть с управляемыми часами и venue/prod/роли. Firefox
|
||
проверяет MAC/IP/диапазон/dBm, устаревание, ошибку и отсутствие сигнала; эти
|
||
состояния Wi-Fi задаются fixture. Отдельно адаптер проверен чтением настоящего
|
||
TR3000 V1 2.5.27-20260804-183625 без изменения настроек роутера.
|
||
|
||
### Аппаратная контрольная точка этапа 15
|
||
|
||
После согласованного обновления реальной площадки, только на тестовой игре:
|
||
|
||
1. Включить сбор Cudy по корневому README; отключить WAN и мобильные данные.
|
||
На Android/iPhone открыть прежние домены, проверить DNS и доверенный HTTPS.
|
||
2. Подключить 100 настоящих Wi-Fi-устройств (несколько вкладок одного профиля
|
||
не заменяют устройства); открыть игру 25 командами, держать нагрузку
|
||
минимум 60 секунд, выполнять ходы и сохранять ответы.
|
||
3. Сверить клиентов Cudy с панелью, диапазоны и доступный сигнал; пройти края
|
||
и проблемные зоны площадки, проверить материалы и действия в каждой зоне.
|
||
MAC/UUID не сопоставлять предположениями; «Нет связи» относится к heartbeat.
|
||
4. Проверить паузу/продолжение, перезапуск venue и повторную регистрацию
|
||
браузеров, смену контекста/несколько вкладок; убедиться, что панели в prod нет.
|
||
5. Временно остановить сборщик: через 30 секунд снимок должен устареть,
|
||
прежние данные и время остаться видимыми. Запустить снова и проверить
|
||
восстановление. Потерю API и восстановление проверить без потери снимка.
|
||
6. Завершить игру, вернуть ZIP на источник, проверить результаты и прежние
|
||
ссылки. Зафиксировать оборудование, число клиентов, длительность,
|
||
задержки/ошибки и покрытие; сообщить результат для приёмки ED-029.
|
||
|
||
Автоматические проверки не заменяют эту приёмку. ED-029 закрыта по явному
|
||
указанию пользователя 2026-10-11; аппаратная приёмка не выполнена.
|
||
Фактический ZIP 1 ГиБ также не проверен.
|
||
|
||
Flow также проверяет переход заполненной БД с числовых ID команд на UUID v7,
|
||
сохранность данных и ограничений, независимое создание команд в трёх схемах
|
||
и полную Go-проверку на временном PostgreSQL. `team_uuid.py` вызывается из flow.
|
||
|
||
## Дизайн-система (без сервера и БД)
|
||
|
||
Запустить фронтенд командой `npm run dev -- --port 5198`, затем из корня
|
||
`python3 tests/venue/design_system.py`. Требуется установленный Firefox.
|
||
Smoke проверяет три ширины, клавиатурные вкладки, повторные карточки и ID,
|
||
локальную форму и окно, состояния, темы и reduced motion.
|
||
|
||
## Проверка очистки
|
||
|
||
`python3 tests/venue/clean.py` проверяет очистку venue с подставным Docker:
|
||
порядок команд, повторный вызов, ошибки и сохранность настроек и посторонних томов.
|
||
Реальные данные не удаляются.
|
||
|
||
### Страница плейлистов
|
||
|
||
После сборки фронтенда: `python3 tests/venue/playlists.py`. Нужен Firefox; тест
|
||
поднимает изолированный API, проверяет загрузку сразу в группу одним запросом, отказ загрузки без потери
|
||
черновика, операции редактора, роли,
|
||
клавиатуру и мобильную ширину. Рабочий сервер и настоящие MP3 не используются.
|