mirror of
https://github.com/coder/coder.git
synced 2025-07-03 16:13:58 +00:00
feat: Add more swagger checks (#5707)
This commit is contained in:
@ -149,6 +149,7 @@ func parseSwaggerComment(commentGroup *ast.CommentGroup) SwaggerComment {
|
||||
|
||||
func VerifySwaggerDefinitions(t *testing.T, router chi.Router, swaggerComments []SwaggerComment) {
|
||||
assertUniqueRoutes(t, swaggerComments)
|
||||
assertSingleAnnotations(t, swaggerComments)
|
||||
|
||||
err := chi.Walk(router, func(method, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error {
|
||||
method = strings.ToLower(method)
|
||||
@ -192,6 +193,36 @@ func assertUniqueRoutes(t *testing.T, comments []SwaggerComment) {
|
||||
}
|
||||
}
|
||||
|
||||
var uniqueAnnotations = []string{"@ID", "@Summary", "@Tags", "@Router"}
|
||||
|
||||
func assertSingleAnnotations(t *testing.T, comments []SwaggerComment) {
|
||||
for _, comment := range comments {
|
||||
counters := map[string]int{}
|
||||
|
||||
for _, line := range comment.raw {
|
||||
splitN := strings.SplitN(strings.TrimSpace(line.Text), " ", 3)
|
||||
if len(splitN) < 2 {
|
||||
continue // comment prefix without any content
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(splitN[1], "@") {
|
||||
continue // not a swagger annotation
|
||||
}
|
||||
|
||||
annotation := splitN[1]
|
||||
if _, ok := counters[annotation]; !ok {
|
||||
counters[annotation] = 0
|
||||
}
|
||||
counters[annotation]++
|
||||
}
|
||||
|
||||
for _, annotation := range uniqueAnnotations {
|
||||
v := counters[annotation]
|
||||
assert.Equal(t, 1, v, "%s annotation for route %s must be defined only once", annotation, comment.router)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func findSwaggerCommentByMethodAndRoute(comments []SwaggerComment, method, route string) *SwaggerComment {
|
||||
for _, c := range comments {
|
||||
if c.method == method && c.router == route {
|
||||
@ -219,6 +250,7 @@ func assertRequiredAnnotations(t *testing.T, comment SwaggerComment) {
|
||||
assert.NotEmpty(t, comment.id, "@ID must be defined")
|
||||
assert.NotEmpty(t, comment.summary, "@Summary must be defined")
|
||||
assert.NotEmpty(t, comment.tags, "@Tags must be defined")
|
||||
assert.NotEmpty(t, comment.router, "@Router must be defined")
|
||||
}
|
||||
|
||||
func assertGoCommentFirst(t *testing.T, comment SwaggerComment) {
|
||||
@ -295,6 +327,8 @@ func assertAccept(t *testing.T, comment SwaggerComment) {
|
||||
}
|
||||
}
|
||||
|
||||
var allowedProduceTypes = []string{"json", "text/event-stream"}
|
||||
|
||||
func assertProduce(t *testing.T, comment SwaggerComment) {
|
||||
var hasResponseModel bool
|
||||
for _, r := range comment.successes {
|
||||
@ -306,6 +340,7 @@ func assertProduce(t *testing.T, comment SwaggerComment) {
|
||||
|
||||
if hasResponseModel {
|
||||
assert.True(t, comment.produce != "", "Route must have @Produce annotation as it responds with a model structure")
|
||||
assert.Contains(t, allowedProduceTypes, comment.produce, "@Produce value is limited to specific types: %s", strings.Join(allowedProduceTypes, ","))
|
||||
} else {
|
||||
if (comment.router == "/workspaceagents/me/app-health" && comment.method == "post") ||
|
||||
(comment.router == "/workspaceagents/me/version" && comment.method == "post") ||
|
||||
|
Reference in New Issue
Block a user