@@ -149,6 +149,7 @@ func parseSwaggerComment(commentGroup *ast.CommentGroup) SwaggerComment {
149
149
150
150
func VerifySwaggerDefinitions (t * testing.T , router chi.Router , swaggerComments []SwaggerComment ) {
151
151
assertUniqueRoutes (t , swaggerComments )
152
+ assertSingleAnnotations (t , swaggerComments )
152
153
153
154
err := chi .Walk (router , func (method , route string , handler http.Handler , middlewares ... func (http.Handler ) http.Handler ) error {
154
155
method = strings .ToLower (method )
@@ -192,6 +193,36 @@ func assertUniqueRoutes(t *testing.T, comments []SwaggerComment) {
192
193
}
193
194
}
194
195
196
+ var uniqueAnnotations = []string {"@ID" , "@Summary" , "@Tags" , "@Router" }
197
+
198
+ func assertSingleAnnotations (t * testing.T , comments []SwaggerComment ) {
199
+ for _ , comment := range comments {
200
+ counters := map [string ]int {}
201
+
202
+ for _ , line := range comment .raw {
203
+ splitN := strings .SplitN (strings .TrimSpace (line .Text ), " " , 3 )
204
+ if len (splitN ) < 2 {
205
+ continue // comment prefix without any content
206
+ }
207
+
208
+ if ! strings .HasPrefix (splitN [1 ], "@" ) {
209
+ continue // not a swagger annotation
210
+ }
211
+
212
+ annotation := splitN [1 ]
213
+ if _ , ok := counters [annotation ]; ! ok {
214
+ counters [annotation ] = 0
215
+ }
216
+ counters [annotation ]++
217
+ }
218
+
219
+ for _ , annotation := range uniqueAnnotations {
220
+ v := counters [annotation ]
221
+ assert .Equal (t , 1 , v , "%s annotation for route %s must be defined only once" , annotation , comment .router )
222
+ }
223
+ }
224
+ }
225
+
195
226
func findSwaggerCommentByMethodAndRoute (comments []SwaggerComment , method , route string ) * SwaggerComment {
196
227
for _ , c := range comments {
197
228
if c .method == method && c .router == route {
@@ -219,6 +250,7 @@ func assertRequiredAnnotations(t *testing.T, comment SwaggerComment) {
219
250
assert .NotEmpty (t , comment .id , "@ID must be defined" )
220
251
assert .NotEmpty (t , comment .summary , "@Summary must be defined" )
221
252
assert .NotEmpty (t , comment .tags , "@Tags must be defined" )
253
+ assert .NotEmpty (t , comment .router , "@Router must be defined" )
222
254
}
223
255
224
256
func assertGoCommentFirst (t * testing.T , comment SwaggerComment ) {
@@ -295,6 +327,8 @@ func assertAccept(t *testing.T, comment SwaggerComment) {
295
327
}
296
328
}
297
329
330
+ var allowedProduceTypes = []string {"json" , "text/event-stream" }
331
+
298
332
func assertProduce (t * testing.T , comment SwaggerComment ) {
299
333
var hasResponseModel bool
300
334
for _ , r := range comment .successes {
@@ -306,6 +340,7 @@ func assertProduce(t *testing.T, comment SwaggerComment) {
306
340
307
341
if hasResponseModel {
308
342
assert .True (t , comment .produce != "" , "Route must have @Produce annotation as it responds with a model structure" )
343
+ assert .Contains (t , allowedProduceTypes , comment .produce , "@Produce value is limited to specific types: %s" , strings .Join (allowedProduceTypes , "," ))
309
344
} else {
310
345
if (comment .router == "/workspaceagents/me/app-health" && comment .method == "post" ) ||
311
346
(comment .router == "/workspaceagents/me/version" && comment .method == "post" ) ||
0 commit comments