github.com/AngusLu/go-swagger@v0.28.0/codescan/routes_test.go (about) 1 package codescan 2 3 import ( 4 "testing" 5 6 "github.com/stretchr/testify/require" 7 8 "github.com/go-openapi/spec" 9 "github.com/stretchr/testify/assert" 10 ) 11 12 func TestRouteExpression(t *testing.T) { 13 assert.Regexp(t, rxRoute, "swagger:route DELETE /orders/{id} deleteOrder") 14 assert.Regexp(t, rxRoute, "swagger:route GET /v1.2/something deleteOrder") 15 } 16 17 func TestRoutesParser(t *testing.T) { 18 sctx := loadClassificationPkgsCtx(t) 19 var ops spec.Paths 20 for _, apiPath := range sctx.app.Routes { 21 prs := &routesBuilder{ 22 ctx: sctx, 23 route: apiPath, 24 operations: make(map[string]*spec.Operation), 25 } 26 require.NoError(t, prs.Build(&ops)) 27 } 28 29 assert.Len(t, ops.Paths, 3) 30 31 po, ok := ops.Paths["/pets"] 32 assert.True(t, ok) 33 assert.NotNil(t, po.Get) 34 assertOperation(t, 35 po.Get, 36 "listPets", 37 "Lists pets filtered by some parameters.", 38 "This will show all available pets by default.\nYou can get the pets that are out of stock", 39 []string{"pets", "users"}, 40 []string{"read", "write"}, 41 ) 42 assertOperation(t, 43 po.Post, 44 "createPet", 45 "Create a pet based on the parameters.", 46 "", 47 []string{"pets", "users"}, 48 []string{"read", "write"}, 49 ) 50 51 po, ok = ops.Paths["/orders"] 52 assert.True(t, ok) 53 assert.NotNil(t, po.Get) 54 assertOperation(t, 55 po.Get, 56 "listOrders", 57 "lists orders filtered by some parameters.", 58 "", 59 []string{"orders"}, 60 []string{"orders:read", "https://www.googleapis.com/auth/userinfo.email"}, 61 ) 62 assertOperation(t, 63 po.Post, 64 "createOrder", 65 "create an order based on the parameters.", 66 "", 67 []string{"orders"}, 68 []string{"read", "write"}, 69 ) 70 71 po, ok = ops.Paths["/orders/{id}"] 72 assert.True(t, ok) 73 assert.NotNil(t, po.Get) 74 assertOperation(t, 75 po.Get, 76 "orderDetails", 77 "gets the details for an order.", 78 "", 79 []string{"orders"}, 80 []string{"read", "write"}, 81 ) 82 83 assertOperation(t, 84 po.Put, 85 "updateOrder", 86 "Update the details for an order.", 87 "When the order doesn't exist this will return an error.", 88 []string{"orders"}, 89 []string{"read", "write"}, 90 ) 91 92 assertOperation(t, 93 po.Delete, 94 "deleteOrder", 95 "delete a particular order.", 96 "", 97 nil, 98 []string{"read", "write"}, 99 ) 100 101 // additional check description tag at Responses 102 rsp, ok := po.Delete.Responses.StatusCodeResponses[202] 103 assert.True(t, ok) 104 assert.Equal(t, "Some description", rsp.Description) 105 assert.Equal(t, "", rsp.Ref.String()) 106 } 107 108 func TestRoutesParserBody(t *testing.T) { 109 sctx, err := newScanCtx(&Options{ 110 Packages: []string{ 111 "github.com/AngusLu/go-swagger/fixtures/goparsing/classification", 112 "github.com/AngusLu/go-swagger/fixtures/goparsing/classification/models", 113 "github.com/AngusLu/go-swagger/fixtures/goparsing/classification/operations", 114 "github.com/AngusLu/go-swagger/fixtures/goparsing/classification/operations_body", 115 }, 116 }) 117 require.NoError(t, err) 118 var ops spec.Paths 119 for _, apiPath := range sctx.app.Routes { 120 prs := &routesBuilder{ 121 ctx: sctx, 122 route: apiPath, 123 operations: make(map[string]*spec.Operation), 124 } 125 require.NoError(t, prs.Build(&ops)) 126 } 127 128 assert.Len(t, ops.Paths, 4) 129 130 po, ok := ops.Paths["/pets"] 131 assert.True(t, ok) 132 assert.NotNil(t, po.Get) 133 assertOperationBody(t, 134 po.Get, 135 "listPets", 136 "Lists pets filtered by some parameters.", 137 "This will show all available pets by default.\nYou can get the pets that are out of stock", 138 []string{"pets", "users"}, 139 []string{"read", "write"}, 140 ) 141 assert.NotNil(t, po.Post) 142 143 assertOperationBody(t, 144 po.Post, 145 "createPet", 146 "Create a pet based on the parameters.", 147 "", 148 []string{"pets", "users"}, 149 []string{"read", "write"}, 150 ) 151 152 po, ok = ops.Paths["/orders"] 153 assert.True(t, ok) 154 assert.NotNil(t, po.Get) 155 assertOperationBody(t, 156 po.Get, 157 "listOrders", 158 "lists orders filtered by some parameters.", 159 "", 160 []string{"orders"}, 161 []string{"orders:read", "https://www.googleapis.com/auth/userinfo.email"}, 162 ) 163 assert.NotNil(t, po.Post) 164 165 assertOperationBody(t, 166 po.Post, 167 "createOrder", 168 "create an order based on the parameters.", 169 "", 170 []string{"orders"}, 171 []string{"read", "write"}, 172 ) 173 174 po, ok = ops.Paths["/orders/{id}"] 175 assert.True(t, ok) 176 assert.NotNil(t, po.Get) 177 assertOperationBody(t, 178 po.Get, 179 "orderDetails", 180 "gets the details for an order.", 181 "", 182 []string{"orders"}, 183 []string{"read", "write"}, 184 ) 185 186 assertOperationBody(t, 187 po.Put, 188 "updateOrder", 189 "Update the details for an order.", 190 "When the order doesn't exist this will return an error.", 191 []string{"orders"}, 192 []string{"read", "write"}, 193 ) 194 195 assertOperationBody(t, 196 po.Delete, 197 "deleteOrder", 198 "delete a particular order.", 199 "", 200 nil, 201 []string{"read", "write"}, 202 ) 203 204 validateRoutesParameters(t, ops) 205 } 206 207 func validateRoutesParameters(t *testing.T, ops spec.Paths) { 208 po := ops.Paths["/pets"] 209 assert.Equal(t, 2, len(po.Post.Parameters)) 210 211 // Testing standard param properties 212 p := po.Post.Parameters[0] 213 assert.Equal(t, "request", p.Name) 214 assert.Equal(t, "body", p.In) 215 assert.Equal(t, "The request model.", p.Description) 216 217 // Testing "required" and "allowEmpty" 218 p = po.Post.Parameters[1] 219 assert.Equal(t, "id", p.Name) 220 assert.Equal(t, "The pet id", p.Description) 221 assert.Equal(t, "path", p.In) 222 assert.Equal(t, true, p.Required) 223 assert.Equal(t, false, p.AllowEmptyValue) 224 225 po = ops.Paths["/orders"] 226 assert.Equal(t, 2, len(po.Post.Parameters)) 227 228 // Testing invalid value for "in" 229 p = po.Post.Parameters[0] 230 assert.Equal(t, "id", p.Name) 231 assert.Equal(t, "The order id", p.Description) 232 assert.Equal(t, "", p.In) // Invalid value should not be set 233 assert.Equal(t, false, p.Required) 234 assert.Equal(t, true, p.AllowEmptyValue) 235 236 p = po.Post.Parameters[1] 237 assert.Equal(t, "request", p.Name) 238 assert.Equal(t, "body", p.In) 239 assert.Equal(t, "The request model.", p.Description) 240 241 po = ops.Paths["/param-test"] 242 assert.Equal(t, 6, len(po.Post.Parameters)) 243 244 // Testing number param with "max" and "min" constraints 245 p = po.Post.Parameters[0] 246 assert.Equal(t, "someNumber", p.Name) 247 assert.Equal(t, "some number", p.Description) 248 assert.Equal(t, "path", p.In) 249 assert.Equal(t, true, p.Required) 250 assert.Equal(t, "number", p.Type) 251 assert.Equal(t, "number", p.Schema.Type[0]) 252 min, max, def := float64(10), float64(20), float64(15) 253 assert.Equal(t, &max, p.Schema.Maximum) 254 assert.Equal(t, &min, p.Schema.Minimum) 255 assert.Equal(t, def, p.Schema.Default) 256 257 // Testing array param provided as query string. Testing "minLength" and "maxLength" constraints for "array" types 258 p = po.Post.Parameters[1] 259 assert.Equal(t, "someQuery", p.Name) 260 assert.Equal(t, "some query values", p.Description) 261 assert.Equal(t, "query", p.In) 262 assert.Equal(t, false, p.Required) 263 assert.Equal(t, "array", p.Type) 264 assert.Equal(t, "array", p.Schema.Type[0]) 265 minLen, maxLen := int64(5), int64(20) 266 assert.Equal(t, &maxLen, p.Schema.MaxLength) 267 assert.Equal(t, &minLen, p.Schema.MinLength) 268 269 // Testing boolean param with default value 270 p = po.Post.Parameters[2] 271 assert.Equal(t, "someBoolean", p.Name) 272 assert.Equal(t, "some boolean", p.Description) 273 assert.Equal(t, "path", p.In) 274 assert.Equal(t, false, p.Required) 275 assert.Equal(t, "boolean", p.Type) 276 assert.Equal(t, "boolean", p.Schema.Type[0]) 277 assert.Equal(t, true, p.Schema.Default) 278 279 // Testing that "min", "max", "minLength" and "maxLength" constraints will only be considered if the right type is provided 280 p = po.Post.Parameters[3] 281 assert.Equal(t, "constraintsOnInvalidType", p.Name) 282 assert.Equal(t, "test constraints on invalid types", p.Description) 283 assert.Equal(t, "query", p.In) 284 assert.Equal(t, "boolean", p.Type) 285 assert.Equal(t, "boolean", p.Schema.Type[0]) 286 assert.Nil(t, p.Schema.Maximum) 287 assert.Nil(t, p.Schema.Minimum) 288 assert.Nil(t, p.Schema.MaxLength) 289 assert.Nil(t, p.Schema.MinLength) 290 assert.Equal(t, "abcde", p.Schema.Format) 291 assert.Equal(t, false, p.Schema.Default) 292 293 // Testing that when "type" is not provided, a schema will not be created 294 p = po.Post.Parameters[4] 295 assert.Equal(t, "noType", p.Name) 296 assert.Equal(t, "test no type", p.Description) 297 assert.Equal(t, "", p.Type) 298 assert.Nil(t, p.Schema) 299 300 // Testing a request body that takes a string value defined by a list of possible values in "enum" 301 p = po.Post.Parameters[5] 302 assert.Equal(t, "request", p.Name) 303 assert.Equal(t, "The request model.", p.Description) 304 assert.Equal(t, "body", p.In) 305 assert.Equal(t, "string", p.Type) 306 assert.Equal(t, "orange", p.Schema.Default) 307 assert.Equal(t, []interface{}{"apple", "orange", "pineapple", "peach", "plum"}, p.Schema.Enum) 308 } 309 310 func assertOperation(t *testing.T, op *spec.Operation, id, summary, description string, tags, scopes []string) { 311 assert.NotNil(t, op) 312 assert.Equal(t, summary, op.Summary) 313 assert.Equal(t, description, op.Description) 314 assert.Equal(t, id, op.ID) 315 assert.EqualValues(t, tags, op.Tags) 316 assert.EqualValues(t, []string{"application/json", "application/x-protobuf"}, op.Consumes) 317 assert.EqualValues(t, []string{"application/json", "application/x-protobuf"}, op.Produces) 318 assert.EqualValues(t, []string{"http", "https", "ws", "wss"}, op.Schemes) 319 assert.Len(t, op.Security, 2) 320 akv, ok := op.Security[0]["api_key"] 321 assert.True(t, ok) 322 // akv must be defined & not empty 323 assert.NotNil(t, akv) 324 assert.Empty(t, akv) 325 326 vv, ok := op.Security[1]["oauth"] 327 assert.True(t, ok) 328 assert.EqualValues(t, scopes, vv) 329 330 assert.NotNil(t, op.Responses.Default) 331 assert.Equal(t, "#/responses/genericError", op.Responses.Default.Ref.String()) 332 333 rsp, ok := op.Responses.StatusCodeResponses[200] 334 assert.True(t, ok) 335 assert.Equal(t, "#/responses/someResponse", rsp.Ref.String()) 336 rsp, ok = op.Responses.StatusCodeResponses[422] 337 assert.True(t, ok) 338 assert.Equal(t, "#/responses/validationError", rsp.Ref.String()) 339 } 340 341 func assertOperationBody(t *testing.T, op *spec.Operation, id, summary, description string, tags, scopes []string) { 342 assert.NotNil(t, op) 343 assert.Equal(t, summary, op.Summary) 344 assert.Equal(t, description, op.Description) 345 assert.Equal(t, id, op.ID) 346 assert.EqualValues(t, tags, op.Tags) 347 assert.EqualValues(t, []string{"application/json", "application/x-protobuf"}, op.Consumes) 348 assert.EqualValues(t, []string{"application/json", "application/x-protobuf"}, op.Produces) 349 assert.EqualValues(t, []string{"http", "https", "ws", "wss"}, op.Schemes) 350 assert.Len(t, op.Security, 2) 351 akv, ok := op.Security[0]["api_key"] 352 assert.True(t, ok) 353 // akv must be defined & not empty 354 assert.NotNil(t, akv) 355 assert.Empty(t, akv) 356 357 vv, ok := op.Security[1]["oauth"] 358 assert.True(t, ok) 359 assert.EqualValues(t, scopes, vv) 360 361 assert.NotNil(t, op.Responses.Default) 362 assert.Equal(t, "", op.Responses.Default.Ref.String()) 363 assert.Equal(t, "#/definitions/genericError", op.Responses.Default.Schema.Ref.String()) 364 365 rsp, ok := op.Responses.StatusCodeResponses[200] 366 assert.True(t, ok) 367 assert.Equal(t, "", rsp.Ref.String()) 368 assert.Equal(t, "#/definitions/someResponse", rsp.Schema.Ref.String()) 369 rsp, ok = op.Responses.StatusCodeResponses[422] 370 assert.True(t, ok) 371 assert.Equal(t, "", rsp.Ref.String()) 372 assert.Equal(t, "#/definitions/validationError", rsp.Schema.Ref.String()) 373 }