package graph import ( "encoding/json" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gitlab.com/unboundsoftware/schemas/graph/model" ) func TestGenerateCosmoRouterConfig(t *testing.T) { tests := []struct { name string subGraphs []*model.SubGraph wantErr bool validate func(t *testing.T, config string) }{ { name: "single subgraph with all fields", subGraphs: []*model.SubGraph{ { Service: "test-service", URL: stringPtr("http://localhost:4001/query"), WsURL: stringPtr("ws://localhost:4001/query"), Sdl: "type Query { test: String }", }, }, wantErr: false, validate: func(t *testing.T, config string) { var result map[string]interface{} err := json.Unmarshal([]byte(config), &result) require.NoError(t, err, "Config should be valid JSON") assert.Equal(t, "1", result["version"], "Version should be 1") subgraphs, ok := result["subgraphs"].([]interface{}) require.True(t, ok, "subgraphs should be an array") require.Len(t, subgraphs, 1, "Should have 1 subgraph") sg := subgraphs[0].(map[string]interface{}) assert.Equal(t, "test-service", sg["name"]) assert.Equal(t, "http://localhost:4001/query", sg["routing_url"]) assert.Equal(t, "type Query { test: String }", sg["sdl"]) subscription, ok := sg["subscription"].(map[string]interface{}) require.True(t, ok, "Should have subscription config") assert.Equal(t, "ws://localhost:4001/query", subscription["url"]) assert.Equal(t, "ws", subscription["protocol"]) assert.Equal(t, "graphql-ws", subscription["websocket_subprotocol"]) }, }, { name: "multiple subgraphs", subGraphs: []*model.SubGraph{ { Service: "service-1", URL: stringPtr("http://localhost:4001/query"), Sdl: "type Query { field1: String }", }, { Service: "service-2", URL: stringPtr("http://localhost:4002/query"), Sdl: "type Query { field2: String }", }, { Service: "service-3", URL: stringPtr("http://localhost:4003/query"), WsURL: stringPtr("ws://localhost:4003/query"), Sdl: "type Subscription { updates: String }", }, }, wantErr: false, validate: func(t *testing.T, config string) { var result map[string]interface{} err := json.Unmarshal([]byte(config), &result) require.NoError(t, err) subgraphs := result["subgraphs"].([]interface{}) assert.Len(t, subgraphs, 3, "Should have 3 subgraphs") // Check first service has no subscription sg1 := subgraphs[0].(map[string]interface{}) assert.Equal(t, "service-1", sg1["name"]) _, hasSubscription := sg1["subscription"] assert.False(t, hasSubscription, "service-1 should not have subscription config") // Check third service has subscription sg3 := subgraphs[2].(map[string]interface{}) assert.Equal(t, "service-3", sg3["name"]) subscription, hasSubscription := sg3["subscription"] assert.True(t, hasSubscription, "service-3 should have subscription config") assert.NotNil(t, subscription) }, }, { name: "subgraph with no URL", subGraphs: []*model.SubGraph{ { Service: "test-service", URL: nil, WsURL: nil, Sdl: "type Query { test: String }", }, }, wantErr: false, validate: func(t *testing.T, config string) { var result map[string]interface{} err := json.Unmarshal([]byte(config), &result) require.NoError(t, err) subgraphs := result["subgraphs"].([]interface{}) sg := subgraphs[0].(map[string]interface{}) // Should not have routing_url or subscription fields if URLs are nil _, hasRoutingURL := sg["routing_url"] assert.False(t, hasRoutingURL, "Should not have routing_url when URL is nil") _, hasSubscription := sg["subscription"] assert.False(t, hasSubscription, "Should not have subscription when WsURL is nil") }, }, { name: "empty subgraphs", subGraphs: []*model.SubGraph{}, wantErr: false, validate: func(t *testing.T, config string) { var result map[string]interface{} err := json.Unmarshal([]byte(config), &result) require.NoError(t, err) subgraphs := result["subgraphs"].([]interface{}) assert.Len(t, subgraphs, 0, "Should have empty subgraphs array") }, }, { name: "nil subgraphs", subGraphs: nil, wantErr: false, validate: func(t *testing.T, config string) { var result map[string]interface{} err := json.Unmarshal([]byte(config), &result) require.NoError(t, err) subgraphs := result["subgraphs"].([]interface{}) assert.Len(t, subgraphs, 0, "Should handle nil subgraphs as empty array") }, }, { name: "complex SDL with multiple types", subGraphs: []*model.SubGraph{ { Service: "complex-service", URL: stringPtr("http://localhost:4001/query"), Sdl: ` type Query { user(id: ID!): User users: [User!]! } type User { id: ID! name: String! email: String! } `, }, }, wantErr: false, validate: func(t *testing.T, config string) { var result map[string]interface{} err := json.Unmarshal([]byte(config), &result) require.NoError(t, err) subgraphs := result["subgraphs"].([]interface{}) sg := subgraphs[0].(map[string]interface{}) sdl := sg["sdl"].(string) assert.Contains(t, sdl, "type Query") assert.Contains(t, sdl, "type User") assert.Contains(t, sdl, "email: String!") }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { config, err := GenerateCosmoRouterConfig(tt.subGraphs) if tt.wantErr { assert.Error(t, err) return } require.NoError(t, err) assert.NotEmpty(t, config, "Config should not be empty") if tt.validate != nil { tt.validate(t, config) } }) } } func TestConvertSubGraphsToCosmo(t *testing.T) { tests := []struct { name string subGraphs []*model.SubGraph wantLen int validate func(t *testing.T, result []map[string]interface{}) }{ { name: "preserves subgraph order", subGraphs: []*model.SubGraph{ {Service: "alpha", URL: stringPtr("http://a"), Sdl: "a"}, {Service: "beta", URL: stringPtr("http://b"), Sdl: "b"}, {Service: "gamma", URL: stringPtr("http://c"), Sdl: "c"}, }, wantLen: 3, validate: func(t *testing.T, result []map[string]interface{}) { assert.Equal(t, "alpha", result[0]["name"]) assert.Equal(t, "beta", result[1]["name"]) assert.Equal(t, "gamma", result[2]["name"]) }, }, { name: "includes SDL exactly as provided", subGraphs: []*model.SubGraph{ { Service: "test", URL: stringPtr("http://test"), Sdl: "type Query { special: String! }", }, }, wantLen: 1, validate: func(t *testing.T, result []map[string]interface{}) { assert.Equal(t, "type Query { special: String! }", result[0]["sdl"]) }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := convertSubGraphsToCosmo(tt.subGraphs) assert.Len(t, result, tt.wantLen) if tt.validate != nil { tt.validate(t, result) } }) } } // Helper function for tests func stringPtr(s string) *string { return &s }