From 8ad680a62836e33b6c46137d4c90350c1db134fa Mon Sep 17 00:00:00 2001 From: Chris Huber Date: Sat, 8 Aug 2026 08:03:40 -0400 Subject: [PATCH] fix: fail editor validation for missing original blocks AI assistance: OpenAI gpt-5.6-terra via OpenCode preserved Gutenberg originalName evidence for core/missing blocks, added failure classification, and ran the editor contract build. Chris Huber remains responsible for every line. --- .../src/editor-command-runners.ts | 14 +++++++++++--- tests/editor-validate-blocks.test.ts | 12 ++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/packages/runtime-playground/src/editor-command-runners.ts b/packages/runtime-playground/src/editor-command-runners.ts index 8a24bdf25..14035caa6 100644 --- a/packages/runtime-playground/src/editor-command-runners.ts +++ b/packages/runtime-playground/src/editor-command-runners.ts @@ -1796,6 +1796,7 @@ const EDITOR_VALIDATE_BLOCKS_READY_TIMEOUT_MS = 30_000 export interface BlockValidationNode { name: string + originalName?: string isValid: boolean issues: string[] innerBlocks?: BlockValidationNode[] @@ -1803,6 +1804,7 @@ export interface BlockValidationNode { export interface BlockValidationResult { name: string + originalName?: string isValid: boolean issues: string[] } @@ -1835,7 +1837,8 @@ export function flattenBlockValidationNodes(nodes: BlockValidationNode[]): Block for (const node of list) { results.push({ name: typeof node.name === "string" ? node.name : "", - isValid: node.isValid !== false, + ...(typeof node.originalName === "string" && node.originalName ? { originalName: node.originalName } : {}), + isValid: node.isValid !== false && !(node.name === "core/missing" && node.originalName), issues: Array.isArray(node.issues) ? node.issues.filter((issue): issue is string => typeof issue === "string") : [], }) if (Array.isArray(node.innerBlocks) && node.innerBlocks.length > 0) { @@ -1916,10 +1919,11 @@ async function evaluateEditorBlockValidation(page: import("playwright").Page, op return String(issue) } - type ValidationNode = { name: string; isValid: boolean; issues: string[]; innerBlocks: ValidationNode[] } + type ValidationNode = { name: string; originalName?: string; isValid: boolean; issues: string[]; innerBlocks: ValidationNode[] } const validateNode = (block: unknown): ValidationNode => { const record = (block && typeof block === "object" ? block : {}) as Record const name = typeof record.name === "string" ? record.name : "" + const originalName = typeof record.originalName === "string" ? record.originalName : "" let isValid = record.isValid !== false let issues: string[] = [] if (typeof validateBlock === "function") { @@ -1942,8 +1946,12 @@ async function evaluateEditorBlockValidation(page: import("playwright").Page, op if (isValid === false && issues.length === 0 && Array.isArray(record.validationIssues)) { issues = (record.validationIssues as unknown[]).map(formatIssue).filter((issue) => issue.length > 0) } + if (name === "core/missing" && originalName) { + isValid = false + if (issues.length === 0) issues = [`Missing editor registration for ${originalName}`] + } const innerBlocks = Array.isArray(record.innerBlocks) ? (record.innerBlocks as unknown[]).map(validateNode) : [] - return { name, isValid, issues, innerBlocks } + return { name, ...(originalName ? { originalName } : {}), isValid, issues, innerBlocks } } const parsed = wpBlocks.parse(content) diff --git a/tests/editor-validate-blocks.test.ts b/tests/editor-validate-blocks.test.ts index ef24fb5b0..efe5106eb 100644 --- a/tests/editor-validate-blocks.test.ts +++ b/tests/editor-validate-blocks.test.ts @@ -25,6 +25,18 @@ const tree: BlockValidationNode[] = [ const flattened = flattenBlockValidationNodes(tree) assert.deepEqual(flattened.map((entry) => entry.name), ["core/columns", "core/column", "core/paragraph"]) +const missingCompanion = summarizeBlockValidation({ + validationProvider: "wordpress-block-editor", + nodes: [{ name: "core/missing", originalName: "blocks-engine/form-input", isValid: true, issues: [] }], +}) +assert.equal(missingCompanion.invalid_blocks, 1) +assert.deepEqual(missingCompanion.results[0], { + name: "core/missing", + originalName: "blocks-engine/form-input", + isValid: false, + issues: [], +}) + // A post with valid blocks: every block isValid, zero invalid. const validResult = summarizeBlockValidation({ validationProvider: "wordpress-block-editor",