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") // Version is a UUID string from wgc version, ok := result["version"].(string) require.True(t, ok, "Version should be a string") assert.NotEmpty(t, version, "Version should not be empty") 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["routingUrl"]) // Check that datasource configurations include subscription settings engineConfig, ok := result["engineConfig"].(map[string]interface{}) require.True(t, ok, "Should have engineConfig") dsConfigs, ok := engineConfig["datasourceConfigurations"].([]interface{}) require.True(t, ok && len(dsConfigs) > 0, "Should have datasource configurations") ds := dsConfigs[0].(map[string]interface{}) customGraphql, ok := ds["customGraphql"].(map[string]interface{}) require.True(t, ok, "Should have customGraphql config") subscription, ok := customGraphql["subscription"].(map[string]interface{}) require.True(t, ok, "Should have subscription config") assert.True(t, subscription["enabled"].(bool), "Subscription should be enabled") subUrl, ok := subscription["url"].(map[string]interface{}) require.True(t, ok, "Should have subscription URL") assert.Equal(t, "ws://localhost:4001/query", subUrl["staticVariableContent"]) }, }, { 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 service names sg1 := subgraphs[0].(map[string]interface{}) assert.Equal(t, "service-1", sg1["name"]) sg3 := subgraphs[2].(map[string]interface{}) assert.Equal(t, "service-3", sg3["name"]) // Check that datasource configurations include subscription for service-3 engineConfig, ok := result["engineConfig"].(map[string]interface{}) require.True(t, ok, "Should have engineConfig") dsConfigs, ok := engineConfig["datasourceConfigurations"].([]interface{}) require.True(t, ok && len(dsConfigs) == 3, "Should have 3 datasource configurations") // Find service-3's datasource config (should have subscription enabled) ds3 := dsConfigs[2].(map[string]interface{}) customGraphql, ok := ds3["customGraphql"].(map[string]interface{}) require.True(t, ok, "Service-3 should have customGraphql config") subscription, ok := customGraphql["subscription"].(map[string]interface{}) require.True(t, ok, "Service-3 should have subscription config") assert.True(t, subscription["enabled"].(bool), "Service-3 subscription should be enabled") }, }, { 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 when URL is nil _, hasRoutingURL := sg["routingUrl"] assert.False(t, hasRoutingURL, "Should not have routingUrl when URL is nil") // Check datasource configurations don't have subscription enabled engineConfig, ok := result["engineConfig"].(map[string]interface{}) require.True(t, ok, "Should have engineConfig") dsConfigs, ok := engineConfig["datasourceConfigurations"].([]interface{}) require.True(t, ok && len(dsConfigs) > 0, "Should have datasource configurations") ds := dsConfigs[0].(map[string]interface{}) customGraphql, ok := ds["customGraphql"].(map[string]interface{}) require.True(t, ok, "Should have customGraphql config") subscription, ok := customGraphql["subscription"].(map[string]interface{}) if ok { // wgc always enables subscription but URL should be empty when WsURL is nil subUrl, hasUrl := subscription["url"].(map[string]interface{}) if hasUrl { _, hasStaticContent := subUrl["staticVariableContent"] assert.False(t, hasStaticContent, "Subscription URL should be empty when WsURL is nil") } } }, }, { name: "empty subgraphs", subGraphs: []*model.SubGraph{}, wantErr: true, validate: nil, }, { name: "nil subgraphs", subGraphs: nil, wantErr: true, validate: nil, }, { 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) // Check the composed graphqlSchema contains the types engineConfig, ok := result["engineConfig"].(map[string]interface{}) require.True(t, ok, "Should have engineConfig") graphqlSchema, ok := engineConfig["graphqlSchema"].(string) require.True(t, ok, "Should have graphqlSchema") assert.Contains(t, graphqlSchema, "Query", "Schema should contain Query type") assert.Contains(t, graphqlSchema, "User", "Schema should contain User type") // Check datasource has the original SDL dsConfigs, ok := engineConfig["datasourceConfigurations"].([]interface{}) require.True(t, ok && len(dsConfigs) > 0, "Should have datasource configurations") ds := dsConfigs[0].(map[string]interface{}) customGraphql, ok := ds["customGraphql"].(map[string]interface{}) require.True(t, ok, "Should have customGraphql config") federation, ok := customGraphql["federation"].(map[string]interface{}) require.True(t, ok, "Should have federation config") serviceSdl, ok := federation["serviceSdl"].(string) require.True(t, ok, "Should have serviceSdl") assert.Contains(t, serviceSdl, "email: String!", "SDL should contain email field") }, }, } 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) } }) } } // Helper function for tests func stringPtr(s string) *string { return &s }