@@ -11,8 +11,10 @@ import type { ExecutionContext } from '@/executor/types'
1111import { ResolvedSecretTraceRegistry } from '@/executor/utils/resolved-secret-trace-registry'
1212import type { SerializedBlock } from '@/serializer/types'
1313import { executeTool } from '@/tools'
14+ import bufferPostFixture from '@/tools/buffer/__fixtures__/post.json'
15+ import { bufferCreatePostTool } from '@/tools/buffer/create_post'
1416import { bufferEditPostTool } from '@/tools/buffer/edit_post'
15- import type { BufferEditPostParams } from '@/tools/buffer/types'
17+ import type { BufferCreatePostParams , BufferEditPostParams } from '@/tools/buffer/types'
1618import { mcpRunOperationTool } from '@/tools/mcp/run-operation'
1719import type { ToolConfig } from '@/tools/types'
1820import { getTool } from '@/tools/utils'
@@ -86,6 +88,10 @@ describe('GenericBlockHandler', () => {
8688 optional : { mode : 'default' , schedulingType : 'default' , approvalChange : 'default' } ,
8789 } ,
8890 { selection : 'cleared structured editors' , optional : { assets : '' , metadata : '' } } ,
91+ {
92+ selection : 'untouched advanced fields' ,
93+ optional : { assets : null , metadata : null , mediaType : null } ,
94+ } ,
8995 ] ) ( 'preserves existing Buffer state for a caption edit with $selection' , async ( { optional } ) => {
9096 mockGetBlock . mockReturnValue ( BufferBlock )
9197 mockGetTool . mockReturnValue ( bufferEditPostTool )
@@ -94,7 +100,7 @@ describe('GenericBlockHandler', () => {
94100 const body : { variables : { input : Record < string , unknown > } } = JSON . parse ( String ( init ?. body ) )
95101 providerInputs . push ( body . variables . input )
96102 return Response . json ( {
97- data : { editPost : { __typename : 'PostActionSuccess' , post : { id : 'post-1' } } } ,
103+ data : { editPost : { __typename : 'PostActionSuccess' , post : bufferPostFixture } } ,
98104 } )
99105 } )
100106 mockExecuteTool . mockImplementation ( async ( toolId : string , params : BufferEditPostParams ) => {
@@ -128,6 +134,93 @@ describe('GenericBlockHandler', () => {
128134 expect ( providerInputs ) . toEqual ( [ { id : 'post-1' , text : 'Updated caption' } ] )
129135 } )
130136
137+ it . each ( [
138+ {
139+ operation : 'create_post' ,
140+ description : 'create defaults with untouched advanced fields' ,
141+ input : {
142+ channelId : 'channel-1' ,
143+ text : 'Caption' ,
144+ mode : 'addToQueue' ,
145+ schedulingType : null ,
146+ mediaType : null ,
147+ needsApproval : null ,
148+ } ,
149+ expected : {
150+ channelId : 'channel-1' ,
151+ text : 'Caption' ,
152+ mode : 'addToQueue' ,
153+ schedulingType : 'automatic' ,
154+ assets : [ ] ,
155+ needsApproval : false ,
156+ } ,
157+ } ,
158+ {
159+ operation : 'edit_post' ,
160+ description : 'media-only edit with an untouched caption' ,
161+ input : {
162+ postId : 'post-1' ,
163+ text : null ,
164+ assets : [ { image : { url : 'https://example.com/image.png' } } ] ,
165+ } ,
166+ expected : {
167+ id : 'post-1' ,
168+ assets : [ { image : { url : 'https://example.com/image.png' } } ] ,
169+ } ,
170+ } ,
171+ {
172+ operation : 'edit_post' ,
173+ description : 'intentional caption clearing' ,
174+ input : { postId : 'post-1' , text : null , clearText : true } ,
175+ expected : { id : 'post-1' , text : null } ,
176+ } ,
177+ ] ) (
178+ 'sends only requested Buffer changes: $description' ,
179+ async ( { operation, input, expected } ) => {
180+ mockGetBlock . mockReturnValue ( BufferBlock )
181+ const tool = operation === 'create_post' ? bufferCreatePostTool : bufferEditPostTool
182+ mockGetTool . mockReturnValue ( tool )
183+ const providerInputs : Record < string , unknown > [ ] = [ ]
184+ vi . spyOn ( globalThis , 'fetch' ) . mockImplementation ( async ( _input , init ) => {
185+ const body : { variables : { input : Record < string , unknown > } } = JSON . parse (
186+ String ( init ?. body )
187+ )
188+ providerInputs . push ( body . variables . input )
189+ return Response . json ( {
190+ data : {
191+ [ operation === 'create_post' ? 'createPost' : 'editPost' ] : {
192+ __typename : 'PostActionSuccess' ,
193+ post : bufferPostFixture ,
194+ } ,
195+ } ,
196+ } )
197+ } )
198+ mockExecuteTool . mockImplementation (
199+ async ( toolId : string , params : BufferCreatePostParams & BufferEditPostParams ) => {
200+ const response = await executeBufferTool ( {
201+ toolId,
202+ input : tool . operation . input ( params ) ,
203+ headers : new Headers ( ) ,
204+ context : { workflowId : mockContext . workflowId , userId : 'user-1' } ,
205+ requestId : 'request-1' ,
206+ } )
207+ if ( ! tool . transformResponse ) throw new Error ( 'Missing response transformer' )
208+ return tool . transformResponse ( response )
209+ }
210+ )
211+ await handler . execute (
212+ mockContext ,
213+ {
214+ ...mockBlock ,
215+ metadata : { id : 'buffer' , name : 'Buffer' } ,
216+ config : { tool : tool . id , params : { } } ,
217+ } ,
218+ { operation, apiKey : 'buffer-key' , ...input }
219+ )
220+ expect ( providerInputs ) . toEqual ( [ expected ] )
221+ }
222+ )
223+
131224 it ( 'executes the standalone stable MCP action after argument resolution with trusted block scope' , async ( ) => {
132225 mockGetBlock . mockReturnValue ( McpBlock )
133226 mockGetTool . mockReturnValue ( mcpRunOperationTool )
0 commit comments