package apiconfig import ( "encoding/json" "git.servflow.io/servflow/definitions/proto" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "testing" ) func TestProtoConfigToAPIConfig(t *testing.T) { tests := []struct { name string input []*proto.WorkflowConfig validate func(t *testing.T, result []*APIConfig) }{ { name: "empty input slice", input: []*proto.WorkflowConfig{}, validate: func(t *testing.T, result []*APIConfig) { assert.Empty(t, result) }, }, { name: "nil config should be skipped", input: []*proto.WorkflowConfig{ nil, }, validate: func(t *testing.T, result []*APIConfig) { assert.Empty(t, result) }, }, { name: "inactive config should be skipped", input: []*proto.WorkflowConfig{ { Id: "test-id", Status: proto.Status_INACTIVE, }, }, validate: func(t *testing.T, result []*APIConfig) { assert.Empty(t, result) }, }, { name: "empty ID should be skipped", input: []*proto.WorkflowConfig{ { Status: proto.Status_ACTIVE, }, }, validate: func(t *testing.T, result []*APIConfig) { assert.Empty(t, result) }, }, { name: "valid config should be converted", input: []*proto.WorkflowConfig{ { Id: "test-id", Status: proto.Status_ACTIVE, ListenPath: "/test", Method: "POST", Request: &proto.Request{ Next: "next-action", ListenPath: "/test", Method: "GET", }, Actions: map[string]*proto.Action{ "action1": { Type: "http", Config: json.RawMessage(`{"url": "http://example.com"}`), Next: "action2", Fail: "error", }, }, Mcp: &proto.MCPConfig{ Enabled: true, Name: "test-tool", Args: map[string]*proto.MCPArgConfig{ "arg1": { Name: "arg1", Type: "string", }, }, Description: "test description", Start: "start", Result: "result", }, Conditionals: map[string]*proto.Conditional{ "cond1": { ValidPath: "valid", InvalidPath: "invalid", Expression: "response.code == 200", }, }, Responses: map[string]*proto.Response{ "success": { Code: 200, Type: "json", Template: []byte(`{"status": "ok"}`), }, }, }, }, validate: func(t *testing.T, result []*APIConfig) { require.Len(t, result, 1) cfg := result[0] // Verify basic fields assert.Equal(t, "test-id", cfg.ID) assert.Equal(t, "/test", cfg.ListenPath) assert.Equal(t, "POST", cfg.Method) // Verify request config assert.Equal(t, "next-action", cfg.Request.Next) // Verify actions require.Contains(t, cfg.Actions, "action1") action := cfg.Actions["action1"] assert.Equal(t, "http", action.Type) assert.JSONEq(t, `{"url": "http://example.com"}`, string(action.Config)) assert.Equal(t, "action2", action.Next) assert.Equal(t, "error", action.Fail) // Verify conditionals require.Contains(t, cfg.Conditionals, "cond1") cond := cfg.Conditionals["cond1"] assert.Equal(t, "valid", cond.ValidPath) assert.Equal(t, "invalid", cond.InvalidPath) assert.Equal(t, "response.code == 200", cond.Expression) // Verify responses require.Contains(t, cfg.Responses, "success") resp := cfg.Responses["success"] assert.Equal(t, 200, resp.Code) assert.Equal(t, "json", resp.Type) assert.Equal(t, `{"status": "ok"}`, resp.Template) assert.Equal(t, MCPToolConfig{ Enabled: true, Name: "test-tool", Args: map[string]ArgType{ "arg1": { Name: "arg1", Type: "string", }, }, Description: "test description", Start: "start", Result: "result", }, cfg.McpTool) assert.Equal(t, HttpConfig{ Next: "next-action", ListenPath: "/test", Method: "GET", }, cfg.HttpConfig) }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := ProtoConfigToAPIConfig(tt.input) tt.validate(t, result) }) } }