From e8d54797bf4f10ff3d59c8df0e746a3a11137c8d Mon Sep 17 00:00:00 2001 From: Virgil Date: Thu, 2 Apr 2026 03:04:55 +0000 Subject: [PATCH] feat(openapi): include graphql tag for playground default path Co-Authored-By: Virgil --- openapi.go | 17 ++++++++++++----- openapi_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/openapi.go b/openapi.go index b65a6ea..895e97b 100644 --- a/openapi.go +++ b/openapi.go @@ -191,10 +191,7 @@ func (sb *SpecBuilder) buildPaths(groups []preparedRouteGroup) map[string]any { }, } - graphqlPath := strings.TrimSpace(sb.GraphQLPath) - if graphqlPath == "" && sb.GraphQLPlayground { - graphqlPath = defaultGraphQLPath - } + graphqlPath := sb.effectiveGraphQLPath() if graphqlPath != "" { graphqlPath = normaliseOpenAPIPath(graphqlPath) paths[graphqlPath] = graphqlPathItem(graphqlPath, operationIDs) @@ -619,7 +616,7 @@ func (sb *SpecBuilder) buildTags(groups []preparedRouteGroup) []map[string]any { } seen := map[string]bool{"system": true} - if graphqlPath := strings.TrimSpace(sb.GraphQLPath); graphqlPath != "" && !seen["graphql"] { + if graphqlPath := sb.effectiveGraphQLPath(); graphqlPath != "" && !seen["graphql"] { tags = append(tags, map[string]any{ "name": "graphql", "description": "GraphQL endpoints", @@ -1624,6 +1621,16 @@ func sseResponseHeaders() map[string]any { } } +// effectiveGraphQLPath returns the configured GraphQL path, or the default +// GraphQL path when playground mode is enabled without an explicit path. +func (sb *SpecBuilder) effectiveGraphQLPath() string { + graphqlPath := strings.TrimSpace(sb.GraphQLPath) + if graphqlPath == "" && sb.GraphQLPlayground { + return defaultGraphQLPath + } + return graphqlPath +} + // documentedResponseHeaders converts route-specific response header metadata // into OpenAPI header objects. func documentedResponseHeaders(headers map[string]string) map[string]any { diff --git a/openapi_test.go b/openapi_test.go index 0d0f13f..77f577e 100644 --- a/openapi_test.go +++ b/openapi_test.go @@ -330,6 +330,37 @@ func TestSpecBuilder_Good_GraphQLPlaygroundDefaultsToGraphQLPath(t *testing.T) { } } +func TestSpecBuilder_Good_GraphQLPlaygroundDefaultsToGraphQLTag(t *testing.T) { + sb := &api.SpecBuilder{ + Title: "Test", + Version: "1.0.0", + GraphQLPlayground: true, + } + + data, err := sb.Build(nil) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + var spec map[string]any + if err := json.Unmarshal(data, &spec); err != nil { + t.Fatalf("invalid JSON: %v", err) + } + + tags := spec["tags"].([]any) + found := false + for _, tag := range tags { + tm := tag.(map[string]any) + if tm["name"] == "graphql" { + found = true + break + } + } + if !found { + t.Fatal("expected graphql tag when playground enables the default GraphQL path") + } +} + func TestSpecBuilder_Good_WebSocketEndpoint(t *testing.T) { sb := &api.SpecBuilder{ Title: "Test",