diff --git a/packages/mcp/test/unit/schema.test.mjs b/packages/mcp/test/unit/schema.test.mjs
index b1b9d417..131a5432 100644
--- a/packages/mcp/test/unit/schema.test.mjs
+++ b/packages/mcp/test/unit/schema.test.mjs
@@ -53,6 +53,10 @@ const cases = {
video: docOf({ type: "video", attrs: { src: "http://x/v.mp4" } }),
youtube: docOf({ type: "youtube", attrs: { src: "http://y/watch" } }),
embed: docOf({ type: "embed", attrs: { src: "http://e", provider: "iframe" } }),
+ htmlEmbed: docOf({
+ type: "htmlEmbed",
+ attrs: { source: "", height: 320 },
+ }),
drawio: docOf({ type: "drawio", attrs: { src: "http://d" } }),
excalidraw: docOf({ type: "excalidraw", attrs: { src: "http://e" } }),
columns: docOf({
@@ -75,3 +79,19 @@ for (const [name, doc] of Object.entries(cases)) {
});
});
}
+
+// htmlEmbed is the sandboxed raw-HTML block. The MCP write path carries it
+// through Yjs (toYdoc -> fromYdoc) without rendering, so a full round-trip must
+// preserve both the `source` snippet and the numeric `height`.
+test("htmlEmbed round-trips source and height through Yjs", () => {
+ const doc = docOf({
+ type: "htmlEmbed",
+ attrs: { source: "", height: 480 },
+ });
+ const ydoc = TiptapTransformer.toYdoc(doc, "default", docmostExtensions);
+ const back = TiptapTransformer.fromYdoc(ydoc, "default");
+ const node = back.content.find((n) => n.type === "htmlEmbed");
+ assert.ok(node, "htmlEmbed node survives the round-trip");
+ assert.equal(node.attrs.source, "");
+ assert.equal(node.attrs.height, 480);
+});