Keep the backlog focused on deferred TESTS; the related non-test gaps (model-allow-list, restriction-cache invalidation, server embed-recursion guard, collectPageEmbeds cycle guard, jest DI/lib0-ESM debt) are now tracked as issues #52-#56 and only linked from the backlog. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6.4 KiB
Отложенные тесты по фичам с коммита 053a9c0d (хвост от PR #49)
Контекст
PR #49 («test: cover features since 053a9c0d + repair test tooling») закрыл
основную массу покрытия новых фич gitmost (+~330 тестов: server/Jest,
client/Vitest, editor-ext/Vitest, packages/mcp/node:test) и починил
тест-инструментарий (FIX-0 сломанные спеки transclusion, BUILD-0 сборка
editor-ext перед серверными тестами, INFRA-0 резолв .tsx email-шаблонов).
Часть тестов из принятого тест-плана намеренно отложена — им нужен тестовый Postgres, реальный Redis или HTTP/e2e-харнес, которых в проекте сейчас нет, либо инвазивный рефактор продакшн-кода. Ниже — что осталось и почему, чтобы не потерять.
1. Интеграционные тесты против БД (нужен тестовый Postgres)
Сейчас все repo-зависимые проверки делаются на моках; SQL-уровень не исполняется. Чтобы покрыть это честно, нужен поднимаемый в CI Postgres (testcontainers или сервис в pipeline) + хелпер миграций.
-
AiAgentRoleRepo— изоляция и индексы.apps/server/src/database/repos/ai-agent-roles/ai-agent-roles.repo.ts. Проверить против реальной БД:findById/listByWorkspaceисключают soft-deleted строки;findByIdдля roleId из ЧУЖОГО workspace → undefined (tenant-изоляция); дубль имени в одном workspace → 23505; то же имя переиспользуемо после softDelete (partial unique indexWHERE deleted_at IS NULL, миграция20260620T120000-ai-agent-roles.ts); одинаковое имя в разных workspace разрешено. Это «хребет» безопасности — сейчас только предполагается unit-моками. -
AiChatRepo.findByCreator— join role-badge.apps/server/src/database/repos/ai-chat/ai-chat.repo.ts(~:27-70). Чат с enabled-ролью → roleName/roleEmoji заполнены; с soft-deleted ролью → бейдж NULL; с DISABLED ролью → бейдж NULL (должно совпадать сresolveRoleForRequest); ORDER BY квалифицированaiChats.*(нет ambiguous column после join). Не проверяемо чистым unit-ом. -
WorkspaceService.update/WorkspaceRepo.updateSetting— jsonb-merge.apps/server/src/core/workspace/services/workspace.service.ts(:514),:275). Сейчас покрыта только форма вызова сервиса (apps/server/src/database/repos/workspace/workspace.repo.ts(workspace-html-embed.spec.ts). Не покрыто (нужна БД):htmlEmbed:trueперсистится через jsonb-merge не затирая соседние настройки (ai, sharing). Это и есть «kill-switch пишется» — критично, что write-половина тоггла не ломает остальной settings-namespace. -
FK
page_template_referencesonDelete('cascade'). Миграция20260620T131000-page-template-references.ts. Проверить, что удаление source/reference-страницы каскадит строки ссылок.
2. HTTP / e2e-харнес (его нет в apps/server)
-
Public-share ассистент: обход per-IP throttle ротацией XFF, но per-workspace cap держит. Контроллер использует стоковый
@UseGuards(ThrottlerGuard)(apps/server/src/core/ai-chat/public-share-chat.controller.ts), IP берётся из FastifytrustProxy→X-Forwarded-For. Единственный оправданный e2e (named journey «аноним спамит ассистента»): ротация XFF обходит per-IP лимит 5/min, но per-workspace cost-cap всё равно отдаёт 429. Требует поднятого HTTP-слоя Nest + trusted-proxy конфигурации. -
Достоверность Lua-окна cost-cap против реального Redis.
apps/server/src/core/ai-chat/public-share-workspace-limiter.ts(SLIDING_WINDOW_LUA). Сейчас cap тестируется против TS-реализацииFakeRedisвpublic-share-chat.spec.ts— баг в самой Lua-строке (>=vs>, неверный PEXPIRE) не поймается. Нужен интеграционный тест против реального/testcontainers Redis.
3. Полная интеграция AiChatService.stream (рефактор R1-stream)
apps/server/src/core/ai-chat/ai-chat.service.ts. В PR #49 извлечён и
покрыт только чистый buildErrorAssistantRecord. Полные интеграционные
сценарии — запись чата, упавшего на первом ходу (onError), жизненный
цикл external-MCP клиентов (закрытие при throw/onFinish), и
история восстанавливается из БД, а не из body.messages (анти-tamper) —
требуют сидирования SDK streamText (инъекция/seam колбэков onError/
onFinish/onAbort + res.hijack). Отложено, чтобы не дестабилизировать
287-строчный stream(); делать вместе с выносом testable turn-pipeline.
Сопутствующие НЕ-тестовые находки
Вынесены в отдельные issues (всплыли во время написания тестов):
- #52 — ai-roles: нет серверной валидации модели роли + дрейф enum драйверов.
- #53 — ws:
invalidateSpaceRestrictionCacheбез вызывающих (30с stale-окно). - #54 — page-embed: серверный guard глубины/циклов раскрытия.
- #55 — transclusion: cycle-guard в
collectPageEmbedsFromPmJson. - #56 — test-infra: jest DI + lib0 ESM (16 падающих сьютов).