Тесты и стенды
> Кратко. Веб проверяют vitest (npm run check — ещё и lint и typecheck) и Playwright e2e на живом стенде; API — pytest. Стенд — API и веб на копии базы города со своим Redis. Инструкция docs/manual собирается из сценариев съёмки и текстов (npm run manual:capture, npm run manual:pages).
Веб: проверки без стенда
| Команда | Что |
|---|---|
npm run lint |
ESLint по всему проекту |
npm run typecheck |
nuxt typecheck (vue-tsc) — идёт минуты |
npm run test |
vitest: tests/**/*.spec.ts, среда happy-dom, tests/setup.ts |
npm run check |
всё сразу: lint, typecheck, test и проверка подсказок значков (check:hints) |
npm run ci |
check и сборка |
Тесты vitest лежат по слоям кода: tests/utils/ (чистые функции: протокол встраивания, подпись вебхуков,
клиенты MCP и ArcGIS), tests/components/, tests/stores/, tests/services/. Один файл:
npx vitest run tests/utils/webhooks.spec.ts.
Веб: Playwright e2e
Сквозные проверки идут по живому стенду и в CI не запускаются (нужна база). Браузер не скачивается: берётся
установленный Chromium Playwright (ревизия под закреплённый @playwright/test), PW_CHROMIUM_PATH или системный
Chrome.
| Где | Что |
|---|---|
e2e/smoke.spec.ts |
карта, карточка, анализ режима, пьезометр, отчёты |
e2e/functions/*.spec.ts |
функции по разделам инструкции: действие → ответ API → результат в окне; запись — с меткой SYNTH-E2E и уборкой |
e2e/functions/developer-api.spec.ts |
API для разработчиков без окна: OpenAPI, OGC, FeatureServer, MCP, API v2, подпись вебхуков, встраивание, PMTiles |
e2e/permissions.spec.ts |
роль и флаги: ответы /auth/config и /auth/me подменяются |
e2e/a11y.spec.ts, e2e/resilience.spec.ts, e2e/visual.spec.ts, e2e/devices.spec.ts |
доступность (axe), сбои сети, эталонные снимки, телефоны и планшеты |
e2e/audit.spec.ts |
обход всех окон на трёх языках (около часа) |
Переменные:
| Переменная | Что | По умолчанию |
|---|---|---|
E2E_BASE_URL |
адрес веба стенда | http://127.0.0.1:3040/itwin-map/ |
E2E_API_URL |
адрес API стенда (проверки ответов, уборка) | http://127.0.0.1:8040 |
E2E_READONLY |
1 — пропустить тесты, которые пишут в базу |
— |
E2E_FRAGMENT_ID |
фрагмент для карты и сверок | 74 |
E2E_TOKEN |
токен входа для стенда с включённым входом (developer-api.spec.ts) |
— |
E2E_LOCALES |
языки e2e/functions.spec.ts |
все три |
E2E_HEADED |
1 — с окном браузера |
— |
Запуск одного набора на собранном стенде:
E2E_BASE_URL=http://127.0.0.1:3090/itwin-map/ E2E_API_URL=http://127.0.0.1:8090 \
npx playwright test e2e/functions/developer-api.spec.ts --project=chromium --workers=1
Прогон этого набора на копии Алматы (07.11.2026): 16 тестов прошли, 4 пропущены — три помечены test.fixme
с найденными ошибками (повтор OBJECTID потребителей, 500 у /api/ogc/jobs, task_status MCP), один требует
стенда с включённым входом.
Правила e2e-тестов: окна открывать через uiStore.requestToolDialog и ждать конца анимации (образец —
openDialog в e2e/functions/operations.spec.ts); сверять числа окна с ответом API; созданные записи помечать
SYNTH-E2E и удалять через API в afterAll; права проверять подменой auth/me; расчёты и вызовы модели ИИ на
общем стенде не запускать (ответы ИИ подменяются, как в e2e/functions/ai.spec.ts). Подробно — docs/e2e-smoke.md.
API: pytest
cd itwin-api
JWT_SECRET=test-secret-test-secret-test-secret-123 AUTH_DISABLED=false \
venv/Scripts/python.exe -m pytest -q tests/test_mcp.py tests/test_arcgis.py tests/test_webhooks.py
# 36 passed
- Тесты маршрутов поднимают приложение через FastAPI
TestClientи подменяют зависимости и базу; живой базы не нужно. tests/pg/— права PostgreSQL на копии базы: только сPG_AUTH_TESTS=1и базой, помеченной как копия.tests/golden/,tests/heatnet/— сверка расчёта с эталонами десктопного sety; нужны эталоны и исходники десктопа.
Стенд на копии базы
Стенд — API, воркер и веб на копии базы города. Боевую базу к стенду не подключают.
- Копия базы:
createdb -T <база города> <база>_copy(или восстановление дампа), так же — копия UsersDB. - API:
.envсDB_NAME=<копия>,USERS_DB_NAME=<копия>, своимREDIS_DB(иначе воркер стенда заберёт чужие задачи из очереди и выполнит их на своей базе),CORS_ALLOWED_ORIGINSс адресом веба стенда. Для стенда без входа —AUTH_DISABLED=true(каждый запрос — пользовательdevсо всеми правами),MUTATIONS_ENABLED=true,TOPOLOGY_MUTATIONS_ENABLED=true; вебхуки выключить —WEBHOOK_POLL_S=0. Запуск:uvicorn main:app --host 127.0.0.1 --port 8090. При первом запуске API сам доводит базу копии (city_schema): таблицыtgid_*, индексы, функции тайлов. - Воркер (для расчётов, выгрузок, запекания):
celery -A worker.celery_app worker -P solo --hostname <имя стенда>@%hс тем же окружением. - Веб: сборка
npm run buildсNUXT_PUBLIC_MAP_API_BASE_URL=http://127.0.0.1:8090, запускnode .output/server/index.mjsсPORT=3090иNUXT_APP_BASE_URL=/itwin-map/. Сборку делайте в отдельной рабочей копии, а не в каталоге, из которого работает служба.npm run devтоже годится, но ленивые окна там грузятся по нескольку секунд, и e2e идут медленнее. - Проверка:
GET /health(база, Redis,city_schema, флаги) иGET /api/v1/auth/config.
Все переменные окружения API и веба — на странице Переменные окружения.
На общем стенде пишите только свои записи с меткой SYNTH-E2E или SYNTH-MANUAL и удаляйте их после проверки.
Ключи ArcGIS, MCP и API v2 отозвать нельзя, а подписаны они секретом JWT_SECRET из .env — на стенде,
который делит секрет с рабочим сервером, их не выпускайте.
Инструкция docs/manual
| Что | Где |
|---|---|
| сценарии съёмки окон | scripts/manual/scenarios/<раздел>.mjs |
| шаги и данные страниц функций | scripts/manual/pages.json |
| тексты страниц | scripts/manual/text/<раздел>/<id>.md: у страницы функции — только разделы «Возможности» … «Для разработчика»; самостоятельная страница начинается со строк keywords, order, level и заголовка # … |
| снимки и видео | npm run manual:capture (MANUAL_BASE_URL, MANUAL_API_URL, MANUAL_STORAGE_PREFIX, MANUAL_ONLY=id1,id2) |
| сборка страниц | npm run manual:pages — пишет docs/manual/** и index.json, проверяет ссылки между страницами и на снимки; битая ссылка — ошибка |
| журнал проверки функций | docs/manual-qa.md |
Съёмку ведут на собранном вебе стенда; записи, созданные для кадра, помечены SYNTH-MANUAL и убираются
сценарием, иначе сценарий падает.
