Symptom

Five roborazzi screenshot scenarios (editor__trigger, editor__filter, editor__executor, editor__datapoint, editor__diagram) produced PNGs showing raw debug text (“Edit: DataPoint”, “id: datapoint-fixture”, “meta: …”) instead of the actual composable editor UI. The other two editor scenarios (editor__calculation-counter, editor__logic-gate) rendered correctly.

Root cause

Two issues:

  1. Scenarios.kt had a private SingleNodeEditorSurface(node: Node) stub composable that rendered raw node fields as plain text. All five failing scenarios called this stub instead of the real edit composables (EditTrigger, EditFilter, EditOutboundWebHook, EditDataPoint, EditDiagram). The two passing scenarios called the real composables directly.

  2. The executor fixture in Fixtures.populatedSwarm() used ExecuteMetaData (the generic executor base type) for the OutgoingWebHook node, but EditOutboundWebHook does a hard cast node.meta as WebHookOutMetaData. This would have caused a ClassCastException once the correct composable was wired up.

Fix

Prevention

When adding a new screenshot scenario for an editor, the stub composable pattern (SingleNodeEditorSurface) should not be used — call the real edit composable directly, following the editor__calculation-counter and editor__logic-gate patterns. The stub was left as a placeholder; the correct composables exist and the Koin context in ScreenshotScope already provides all required DI bindings. Additionally, fixture metadata types must match the hard cast in the target composable’s remember { mutableStateOf(node.meta as XMetaData) } — use the specific subtype, not the base ExecuteMetaData.