@@ -161,6 +161,56 @@ vi.mock('@/blocks', () => ({
161161 subreddit : { type : 'string' } ,
162162 } ,
163163 } ,
164+ // Mock block with both basic and advanced mode fields for testing
165+ slack : {
166+ name : 'Slack' ,
167+ description : 'Send messages to Slack' ,
168+ category : 'tools' ,
169+ bgColor : '#611f69' ,
170+ tools : {
171+ access : [ 'slack_send_message' ] ,
172+ config : {
173+ tool : ( ) => 'slack_send_message' ,
174+ } ,
175+ } ,
176+ subBlocks : [
177+ { id : 'channel' , type : 'dropdown' , title : 'Channel' , mode : 'basic' } ,
178+ { id : 'manualChannel' , type : 'short-input' , title : 'Channel ID' , mode : 'advanced' } ,
179+ { id : 'text' , type : 'long-input' , title : 'Message' } , // mode: 'both' (default)
180+ { id : 'username' , type : 'short-input' , title : 'Username' , mode : 'both' } ,
181+ ] ,
182+ inputs : {
183+ channel : { type : 'string' } ,
184+ manualChannel : { type : 'string' } ,
185+ text : { type : 'string' } ,
186+ username : { type : 'string' } ,
187+ } ,
188+ } ,
189+ // Mock agent block with memories for testing
190+ agentWithMemories : {
191+ name : 'Agent with Memories' ,
192+ description : 'AI Agent with memory support' ,
193+ category : 'ai' ,
194+ bgColor : '#2196F3' ,
195+ tools : {
196+ access : [ 'anthropic_chat' ] ,
197+ config : {
198+ tool : ( ) => 'anthropic_chat' ,
199+ } ,
200+ } ,
201+ subBlocks : [
202+ { id : 'systemPrompt' , type : 'long-input' , title : 'System Prompt' } , // mode: 'both' (default)
203+ { id : 'userPrompt' , type : 'long-input' , title : 'User Prompt' } , // mode: 'both' (default)
204+ { id : 'memories' , type : 'short-input' , title : 'Memories' , mode : 'advanced' } ,
205+ { id : 'model' , type : 'dropdown' , title : 'Model' } , // mode: 'both' (default)
206+ ] ,
207+ inputs : {
208+ systemPrompt : { type : 'string' } ,
209+ userPrompt : { type : 'string' } ,
210+ memories : { type : 'array' } ,
211+ model : { type : 'string' } ,
212+ } ,
213+ } ,
164214 }
165215
166216 return mockConfigs [ type ] || null
@@ -716,4 +766,200 @@ describe('Serializer', () => {
716766 } ) . toThrow ( 'Test Reddit Block is missing required fields: Reddit Account' )
717767 } )
718768 } )
769+
770+ /**
771+ * Advanced mode field filtering tests
772+ */
773+ describe ( 'advanced mode field filtering' , ( ) => {
774+ it . concurrent ( 'should include all fields when block is in advanced mode' , ( ) => {
775+ const serializer = new Serializer ( )
776+
777+ const advancedModeBlock : any = {
778+ id : 'slack-1' ,
779+ type : 'slack' ,
780+ name : 'Test Slack Block' ,
781+ position : { x : 0 , y : 0 } ,
782+ advancedMode : true , // Advanced mode enabled
783+ subBlocks : {
784+ channel : { value : 'general' } , // basic mode field
785+ manualChannel : { value : 'C1234567890' } , // advanced mode field
786+ text : { value : 'Hello world' } , // both mode field
787+ username : { value : 'bot' } , // both mode field
788+ } ,
789+ outputs : { } ,
790+ enabled : true ,
791+ }
792+
793+ const serialized = serializer . serializeWorkflow ( { 'slack-1' : advancedModeBlock } , [ ] , { } )
794+
795+ const slackBlock = serialized . blocks . find ( ( b ) => b . id === 'slack-1' )
796+ expect ( slackBlock ) . toBeDefined ( )
797+
798+ // In advanced mode, should include ALL fields (basic, advanced, and both)
799+ expect ( slackBlock ?. config . params . channel ) . toBe ( 'general' ) // basic mode field included
800+ expect ( slackBlock ?. config . params . manualChannel ) . toBe ( 'C1234567890' ) // advanced mode field included
801+ expect ( slackBlock ?. config . params . text ) . toBe ( 'Hello world' ) // both mode field included
802+ expect ( slackBlock ?. config . params . username ) . toBe ( 'bot' ) // both mode field included
803+ } )
804+
805+ it . concurrent ( 'should exclude advanced-only fields when block is in basic mode' , ( ) => {
806+ const serializer = new Serializer ( )
807+
808+ const basicModeBlock : any = {
809+ id : 'slack-1' ,
810+ type : 'slack' ,
811+ name : 'Test Slack Block' ,
812+ position : { x : 0 , y : 0 } ,
813+ advancedMode : false , // Basic mode enabled
814+ subBlocks : {
815+ channel : { value : 'general' } , // basic mode field
816+ manualChannel : { value : 'C1234567890' } , // advanced mode field
817+ text : { value : 'Hello world' } , // both mode field
818+ username : { value : 'bot' } , // both mode field
819+ } ,
820+ outputs : { } ,
821+ enabled : true ,
822+ }
823+
824+ const serialized = serializer . serializeWorkflow ( { 'slack-1' : basicModeBlock } , [ ] , { } )
825+
826+ const slackBlock = serialized . blocks . find ( ( b ) => b . id === 'slack-1' )
827+ expect ( slackBlock ) . toBeDefined ( )
828+
829+ // In basic mode, should include basic-only fields and exclude advanced-only fields
830+ expect ( slackBlock ?. config . params . channel ) . toBe ( 'general' ) // basic mode field included
831+ expect ( slackBlock ?. config . params . manualChannel ) . toBeUndefined ( ) // advanced mode field excluded
832+ expect ( slackBlock ?. config . params . text ) . toBe ( 'Hello world' ) // both mode field included
833+ expect ( slackBlock ?. config . params . username ) . toBe ( 'bot' ) // both mode field included
834+ } )
835+
836+ it . concurrent (
837+ 'should exclude advanced-only fields when advancedMode is undefined (defaults to basic mode)' ,
838+ ( ) => {
839+ const serializer = new Serializer ( )
840+
841+ const defaultModeBlock : any = {
842+ id : 'slack-1' ,
843+ type : 'slack' ,
844+ name : 'Test Slack Block' ,
845+ position : { x : 0 , y : 0 } ,
846+ // advancedMode: undefined (defaults to false)
847+ subBlocks : {
848+ channel : { value : 'general' } , // basic mode field
849+ manualChannel : { value : 'C1234567890' } , // advanced mode field
850+ text : { value : 'Hello world' } , // both mode field
851+ username : { value : 'bot' } , // both mode field
852+ } ,
853+ outputs : { } ,
854+ enabled : true ,
855+ }
856+
857+ const serialized = serializer . serializeWorkflow ( { 'slack-1' : defaultModeBlock } , [ ] , { } )
858+
859+ const slackBlock = serialized . blocks . find ( ( b ) => b . id === 'slack-1' )
860+ expect ( slackBlock ) . toBeDefined ( )
861+
862+ // Should default to basic mode behavior (include basic + both, exclude advanced)
863+ expect ( slackBlock ?. config . params . channel ) . toBe ( 'general' ) // basic mode field included
864+ expect ( slackBlock ?. config . params . manualChannel ) . toBeUndefined ( ) // advanced mode field excluded
865+ expect ( slackBlock ?. config . params . text ) . toBe ( 'Hello world' ) // both mode field included
866+ expect ( slackBlock ?. config . params . username ) . toBe ( 'bot' ) // both mode field included
867+ }
868+ )
869+
870+ it . concurrent ( 'should filter memories field correctly in agent blocks' , ( ) => {
871+ const serializer = new Serializer ( )
872+
873+ const agentInBasicMode : any = {
874+ id : 'agent-1' ,
875+ type : 'agentWithMemories' ,
876+ name : 'Test Agent' ,
877+ position : { x : 0 , y : 0 } ,
878+ advancedMode : false , // Basic mode
879+ subBlocks : {
880+ systemPrompt : { value : 'You are helpful' } , // both mode field
881+ userPrompt : { value : 'Hello' } , // both mode field
882+ memories : { value : [ { role : 'user' , content : 'My name is John' } ] } , // advanced mode field
883+ model : { value : 'claude-3-sonnet' } , // both mode field
884+ } ,
885+ outputs : { } ,
886+ enabled : true ,
887+ }
888+
889+ const serialized = serializer . serializeWorkflow ( { 'agent-1' : agentInBasicMode } , [ ] , { } )
890+
891+ const agentBlock = serialized . blocks . find ( ( b ) => b . id === 'agent-1' )
892+ expect ( agentBlock ) . toBeDefined ( )
893+
894+ // In basic mode, memories should be excluded
895+ expect ( agentBlock ?. config . params . systemPrompt ) . toBe ( 'You are helpful' )
896+ expect ( agentBlock ?. config . params . userPrompt ) . toBe ( 'Hello' )
897+ expect ( agentBlock ?. config . params . memories ) . toBeUndefined ( ) // Excluded in basic mode
898+ expect ( agentBlock ?. config . params . model ) . toBe ( 'claude-3-sonnet' )
899+ } )
900+
901+ it . concurrent ( 'should include memories field when agent is in advanced mode' , ( ) => {
902+ const serializer = new Serializer ( )
903+
904+ const agentInAdvancedMode : any = {
905+ id : 'agent-1' ,
906+ type : 'agentWithMemories' ,
907+ name : 'Test Agent' ,
908+ position : { x : 0 , y : 0 } ,
909+ advancedMode : true , // Advanced mode
910+ subBlocks : {
911+ systemPrompt : { value : 'You are helpful' } , // both mode field
912+ userPrompt : { value : 'Hello' } , // both mode field
913+ memories : { value : [ { role : 'user' , content : 'My name is John' } ] } , // advanced mode field
914+ model : { value : 'claude-3-sonnet' } , // both mode field
915+ } ,
916+ outputs : { } ,
917+ enabled : true ,
918+ }
919+
920+ const serialized = serializer . serializeWorkflow ( { 'agent-1' : agentInAdvancedMode } , [ ] , { } )
921+
922+ const agentBlock = serialized . blocks . find ( ( b ) => b . id === 'agent-1' )
923+ expect ( agentBlock ) . toBeDefined ( )
924+
925+ // In advanced mode, memories should be included
926+ expect ( agentBlock ?. config . params . systemPrompt ) . toBe ( 'You are helpful' )
927+ expect ( agentBlock ?. config . params . userPrompt ) . toBe ( 'Hello' )
928+ expect ( agentBlock ?. config . params . memories ) . toEqual ( [
929+ { role : 'user' , content : 'My name is John' } ,
930+ ] ) // Included in advanced mode
931+ expect ( agentBlock ?. config . params . model ) . toBe ( 'claude-3-sonnet' )
932+ } )
933+
934+ it . concurrent ( 'should handle blocks with no matching subblock config gracefully' , ( ) => {
935+ const serializer = new Serializer ( )
936+
937+ const blockWithUnknownField : any = {
938+ id : 'slack-1' ,
939+ type : 'slack' ,
940+ name : 'Test Slack Block' ,
941+ position : { x : 0 , y : 0 } ,
942+ advancedMode : false , // Basic mode
943+ subBlocks : {
944+ channel : { value : 'general' } , // known field
945+ unknownField : { value : 'someValue' } , // field not in config
946+ text : { value : 'Hello world' } , // known field
947+ } ,
948+ outputs : { } ,
949+ enabled : true ,
950+ }
951+
952+ const serialized = serializer . serializeWorkflow ( { 'slack-1' : blockWithUnknownField } , [ ] , { } )
953+
954+ const slackBlock = serialized . blocks . find ( ( b ) => b . id === 'slack-1' )
955+ expect ( slackBlock ) . toBeDefined ( )
956+
957+ // Known fields should be processed according to mode rules
958+ expect ( slackBlock ?. config . params . channel ) . toBe ( 'general' )
959+ expect ( slackBlock ?. config . params . text ) . toBe ( 'Hello world' )
960+
961+ // Unknown fields are filtered out (no subblock config found, so shouldIncludeField is not called)
962+ expect ( slackBlock ?. config . params . unknownField ) . toBeUndefined ( )
963+ } )
964+ } )
719965} )
0 commit comments