test: покрыть тестами sandbox HTML-embed и trackerHead (ревью 81823fce..HEAD) #99
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Контекст
Финальное мульти-аспектное ревью коммитов
81823fce^..HEAD(sandbox HTML-embed, admin-onlytrackerHead, удаление role-gating) показало: реализация корректна и безопасна, но самые чувствительные новые пути поставлены без тестов. Issue собирает пробелы покрытия для закрытия перед релизом.Уже покрыто (для контекста, не трогаем):
prepareContentForShare(toggle ON/OFF/absent/workspace-missing + транклюзия) вshare-html-embed.spec.ts; персистентностьtrackerHead(updateSetting) вworkspace-html-embed.spec.ts; чистые хелперы песочницы (buildSandboxSrcdoc/shouldRender/canEdit) вhtml-embed-sandbox.test.ts.Пробелы покрытия
1. Инъекция
trackerHeadв<head>— нулевое покрытие (важно)Файл:
apps/server/src/core/share/share-seo.controller.ts(≈L93–115)Самый чувствительный новый путь (verbatim-инъекция доверенного admin-сниппета в origin публичной страницы) не покрыт ни одним spec. Непокрытые ветки:
String.replaceинтерпретировал бы$&/$`/$'/$$внутри сниппета как шаблоны подстановки и портил бы трекер;</head>(logger.warn, без инъекции);trackerHead→ инъекции нет.Что сделать: вынести инъекцию в чистый хелпер
injectTrackerHead(html, trackerHead): stringи покрыть юнит-тестами:$&/$$/$`/$'вставляется байт-в-байт перед</head>(тест падает на до-фиксовом строковом replace);</head>→ html без изменений.2. Passthrough-узел
htmlEmbedв mcp-схеме без round-trip теста (важно)Файл:
packages/mcp/src/lib/docmost-schema.ts(узелHtmlEmbed)Узел добавлен, чтобы
TiptapTransformer.toYdocне падал сUnknown node type: htmlEmbedпри MCP/AI-правке страницы с embed. Вpackages/mcp/test— ноль упоминанийhtmlEmbed, фикс не зафиксирован тестом; удаление узла изdocmostExtensionsмолча вернёт падение.Что сделать: добавить
htmlEmbedв объектcasesвpackages/mcp/test/unit/schema.test.mjs(там уже есть acceptance-цикл поtoYdoc); кейс round-trip, проверяющий сохранениеsource/height.3. Клиентский авто-resize / валидация источника / clampHeight / sandbox-атрибут (важно)
Файл:
apps/client/src/features/editor/components/html-embed/html-embed-view.tsx(≈L54–95, L156)html-embed-sandbox.test.tsп��крывает только чистые хелперы. Непокрыто:event.source !== iframeRef.current?.contentWindow(единственная защита от чужого окна);Number.isFinite-гард (NaN→игнор);clampHeight[40, 4000];sandbox="allow-scripts allow-popups allow-forms"(несущее свойство всей защиты от XSS) — ничем не застрахован от регрессии.Что сделать: вынести предикаты (
isTrustedHeightMessage, экспортироватьclampHeight) вhtml-embed-sandbox.tsи юнит-тестировать (чужой source отвергнут, неверный тип отвергнут, NaN/Infinity → нет апдейта, clamp на обеих границах); добавить тест/ассерт, что у iframe ровно эти три sandbox-токена безallow-same-originи заданsrcDoc, а неsrc.4. Атрибут
heightв editor-ext (parse/render + NaN-гард)Файл:
packages/editor-ext/src/lib/html-embed/html-embed.ts(≈L96–105)Существующий
html-embed-codec.spec.tsпокрывает только кодекsource. Проверить parseHTML:"120"→120, отсутствует→null,"abc"→null (NaN-гард, падает на до-фиксовомparseInt-only коде),"120px"→120; renderHTML: 120→{"data-height":"120"}, null/0→{}.5. Валидация DTO
trackerHead(@IsString/@MaxLength(20000))Файл:
apps/server/src/core/workspace/dto/update-workspace.dto.ts(≈L62–67)Валидация не тестируется; новый
workspace-html-embed.spec.tsобходит ValidationPipe черезas any, так что предел 20000 символов и проверка типа не проверяются. В проекте нет прецедента*.dto.spec.ts, поэтому это самый нижний приоритет — ноMaxLengthэто реальная граница на влияемый админом ввод в<head>.(Опционально, связанное) Контрактный тест против дрейфа схемы
Схема
htmlEmbedживёт в трёх копиях (editor-ext — канон, mcp — ручное зеркало, server-util). Лёгкий контрактный тест, прогоняющий фикстуру через editor-ext и mcp-зеркало и сверяющий имя узла + ключи атрибутов, превратил бы молчаливый рантайм-дрейф в падение CI. Не обязательно в рамках этого issue.Definition of Done
injectTrackerHead+ юнит-тесты (вкл.$-последовательности)htmlEmbedв mcpheightв editor-ext (вкл. NaN-гард)trackerHeadIssue создан по результатам код-ревью (skill
code-review-orchestrator), диапазон81823fce^..HEAD.