github.com/go-swagger/go-swagger@v0.31.0/codescan/parameters_test.go (about)

     1  package codescan
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/go-openapi/spec"
     7  	"github.com/stretchr/testify/assert"
     8  	"github.com/stretchr/testify/require"
     9  )
    10  
    11  const (
    12  	gcBadEnum = "bad_enum"
    13  )
    14  
    15  func getParameter(sctx *scanCtx, nm string) *entityDecl {
    16  	for _, v := range sctx.app.Parameters {
    17  		param := v
    18  		if v.Ident.Name == nm {
    19  			return param
    20  		}
    21  	}
    22  	return nil
    23  }
    24  
    25  func TestScanFileParam(t *testing.T) {
    26  	sctx := loadClassificationPkgsCtx(t)
    27  	operations := make(map[string]*spec.Operation)
    28  	for _, rn := range []string{"OrderBodyParams", "MultipleOrderParams", "ComplexerOneParams", "NoParams", "NoParamsAlias", "MyFileParams", "MyFuncFileParams", "EmbeddedFileParams"} {
    29  		td := getParameter(sctx, rn)
    30  
    31  		prs := &parameterBuilder{
    32  			ctx:  sctx,
    33  			decl: td,
    34  		}
    35  		require.NoError(t, prs.Build(operations))
    36  	}
    37  	assert.Len(t, operations, 10)
    38  
    39  	of, ok := operations["myOperation"]
    40  	assert.True(t, ok)
    41  	assert.Len(t, of.Parameters, 1)
    42  	fileParam := of.Parameters[0]
    43  	assert.Equal(t, "MyFormFile desc.", fileParam.Description)
    44  	assert.Equal(t, "formData", fileParam.In)
    45  	assert.Equal(t, "file", fileParam.Type)
    46  	assert.False(t, fileParam.Required)
    47  
    48  	emb, ok := operations["myOtherOperation"]
    49  	assert.True(t, ok)
    50  	assert.Len(t, emb.Parameters, 2)
    51  	fileParam = emb.Parameters[0]
    52  	assert.Equal(t, "MyFormFile desc.", fileParam.Description)
    53  	assert.Equal(t, "formData", fileParam.In)
    54  	assert.Equal(t, "file", fileParam.Type)
    55  	assert.False(t, fileParam.Required)
    56  	extraParam := emb.Parameters[1]
    57  	assert.Equal(t, "ExtraParam desc.", extraParam.Description)
    58  	assert.Equal(t, "formData", extraParam.In)
    59  	assert.Equal(t, "integer", extraParam.Type)
    60  	assert.True(t, extraParam.Required)
    61  
    62  	ffp, ok := operations["myFuncOperation"]
    63  	assert.True(t, ok)
    64  	assert.Len(t, ffp.Parameters, 1)
    65  	fileParam = ffp.Parameters[0]
    66  	assert.Equal(t, "MyFormFile desc.", fileParam.Description)
    67  	assert.Equal(t, "formData", fileParam.In)
    68  	assert.Equal(t, "file", fileParam.Type)
    69  	assert.False(t, fileParam.Required)
    70  }
    71  
    72  func TestParamsParser(t *testing.T) {
    73  	sctx := loadClassificationPkgsCtx(t)
    74  	operations := make(map[string]*spec.Operation)
    75  	for _, rn := range []string{"OrderBodyParams", "MultipleOrderParams", "ComplexerOneParams", "NoParams", "NoParamsAlias", "MyFileParams", "MyFuncFileParams", "EmbeddedFileParams"} {
    76  		td := getParameter(sctx, rn)
    77  
    78  		prs := &parameterBuilder{
    79  			ctx:  sctx,
    80  			decl: td,
    81  		}
    82  		require.NoError(t, prs.Build(operations))
    83  	}
    84  
    85  	assert.Len(t, operations, 10)
    86  	cr, okParam := operations["yetAnotherOperation"]
    87  	assert.True(t, okParam)
    88  	assert.Len(t, cr.Parameters, 8)
    89  	for _, param := range cr.Parameters {
    90  		switch param.Name {
    91  		case "id":
    92  			assert.Equal(t, "integer", param.Type)
    93  			assert.Equal(t, "int64", param.Format)
    94  		case "name":
    95  			assert.Equal(t, "string", param.Type)
    96  			assert.Equal(t, "", param.Format)
    97  		case "age":
    98  			assert.Equal(t, "integer", param.Type)
    99  			assert.Equal(t, "int32", param.Format)
   100  		case "notes":
   101  			assert.Equal(t, "string", param.Type)
   102  			assert.Equal(t, "", param.Format)
   103  		case "extra":
   104  			assert.Equal(t, "string", param.Type)
   105  			assert.Equal(t, "", param.Format)
   106  		case "createdAt":
   107  			assert.Equal(t, "string", param.Type)
   108  			assert.Equal(t, "date-time", param.Format)
   109  		case "informity":
   110  			assert.Equal(t, "string", param.Type)
   111  			assert.Equal(t, "formData", param.In)
   112  		case "NoTagName":
   113  			assert.Equal(t, "string", param.Type)
   114  			assert.Equal(t, "", param.Format)
   115  		default:
   116  			assert.Fail(t, "unknown property: "+param.Name)
   117  		}
   118  	}
   119  
   120  	ob, okParam := operations["updateOrder"]
   121  	assert.True(t, okParam)
   122  	assert.Len(t, ob.Parameters, 1)
   123  	bodyParam := ob.Parameters[0]
   124  	assert.Equal(t, "The order to submit.", bodyParam.Description)
   125  	assert.Equal(t, "body", bodyParam.In)
   126  	assert.Equal(t, "#/definitions/order", bodyParam.Schema.Ref.String())
   127  	assert.True(t, bodyParam.Required)
   128  
   129  	mop, okParam := operations["getOrders"]
   130  	assert.True(t, okParam)
   131  	assert.Len(t, mop.Parameters, 2)
   132  	ordersParam := mop.Parameters[0]
   133  	assert.Equal(t, "The orders", ordersParam.Description)
   134  	assert.True(t, ordersParam.Required)
   135  	assert.Equal(t, "array", ordersParam.Type)
   136  	otherParam := mop.Parameters[1]
   137  	assert.Equal(t, "And another thing", otherParam.Description)
   138  
   139  	op, okParam := operations["someOperation"]
   140  	assert.True(t, okParam)
   141  	assert.Len(t, op.Parameters, 12)
   142  
   143  	for _, param := range op.Parameters {
   144  		switch param.Name {
   145  		case "id":
   146  			assert.Equal(t, "ID of this no model instance.\nids in this application start at 11 and are smaller than 1000", param.Description)
   147  			assert.Equal(t, "path", param.In)
   148  			assert.Equal(t, "integer", param.Type)
   149  			assert.Equal(t, "int64", param.Format)
   150  			assert.True(t, param.Required)
   151  			assert.Equal(t, "ID", param.Extensions["x-go-name"])
   152  			assert.EqualValues(t, 1000, *param.Maximum)
   153  			assert.True(t, param.ExclusiveMaximum)
   154  			assert.EqualValues(t, 10, *param.Minimum)
   155  			assert.True(t, param.ExclusiveMinimum)
   156  			assert.Equal(t, 1, param.Default, "%s default value is incorrect", param.Name)
   157  
   158  		case "score":
   159  			assert.Equal(t, "The Score of this model", param.Description)
   160  			assert.Equal(t, "query", param.In)
   161  			assert.Equal(t, "integer", param.Type)
   162  			assert.Equal(t, "int32", param.Format)
   163  			assert.True(t, param.Required)
   164  			assert.Equal(t, "Score", param.Extensions["x-go-name"])
   165  			assert.EqualValues(t, 45, *param.Maximum)
   166  			assert.False(t, param.ExclusiveMaximum)
   167  			assert.EqualValues(t, 3, *param.Minimum)
   168  			assert.False(t, param.ExclusiveMinimum)
   169  			assert.Equal(t, 2, param.Default, "%s default value is incorrect", param.Name)
   170  			assert.Equal(t, 27, param.Example)
   171  
   172  		case "x-hdr-name":
   173  			assert.Equal(t, "Name of this no model instance", param.Description)
   174  			assert.Equal(t, "header", param.In)
   175  			assert.Equal(t, "string", param.Type)
   176  			assert.True(t, param.Required)
   177  			assert.Equal(t, "Name", param.Extensions["x-go-name"])
   178  			assert.EqualValues(t, 4, *param.MinLength)
   179  			assert.EqualValues(t, 50, *param.MaxLength)
   180  			assert.Equal(t, "[A-Za-z0-9-.]*", param.Pattern)
   181  
   182  		case "created":
   183  			assert.Equal(t, "Created holds the time when this entry was created", param.Description)
   184  			assert.Equal(t, "query", param.In)
   185  			assert.Equal(t, "string", param.Type)
   186  			assert.Equal(t, "date-time", param.Format)
   187  			assert.False(t, param.Required)
   188  			assert.Equal(t, "Created", param.Extensions["x-go-name"])
   189  
   190  		case "category_old":
   191  			assert.Equal(t, "The Category of this model (old enum format)", param.Description)
   192  			assert.Equal(t, "query", param.In)
   193  			assert.Equal(t, "string", param.Type)
   194  			assert.True(t, param.Required)
   195  			assert.Equal(t, "CategoryOld", param.Extensions["x-go-name"])
   196  			assert.EqualValues(t, []interface{}{"foo", "bar", "none"}, param.Enum, "%s enum values are incorrect", param.Name)
   197  			assert.Equal(t, "bar", param.Default, "%s default value is incorrect", param.Name)
   198  		case "category":
   199  			assert.Equal(t, "The Category of this model", param.Description)
   200  			assert.Equal(t, "query", param.In)
   201  			assert.Equal(t, "string", param.Type)
   202  			assert.True(t, param.Required)
   203  			assert.Equal(t, "Category", param.Extensions["x-go-name"])
   204  			assert.EqualValues(t, []interface{}{"foo", "bar", "none"}, param.Enum, "%s enum values are incorrect", param.Name)
   205  			assert.Equal(t, "bar", param.Default, "%s default value is incorrect", param.Name)
   206  		case "type_old":
   207  			assert.Equal(t, "Type of this model (old enum format)", param.Description)
   208  			assert.Equal(t, "query", param.In)
   209  			assert.Equal(t, "integer", param.Type)
   210  			assert.EqualValues(t, []interface{}{1, 3, 5}, param.Enum, "%s enum values are incorrect", param.Name)
   211  		case "type":
   212  			assert.Equal(t, "Type of this model", param.Description)
   213  			assert.Equal(t, "query", param.In)
   214  			assert.Equal(t, "integer", param.Type)
   215  			assert.EqualValues(t, []interface{}{1, 3, 5}, param.Enum, "%s enum values are incorrect", param.Name)
   216  		case gcBadEnum:
   217  			assert.Equal(t, "query", param.In)
   218  			assert.Equal(t, "integer", param.Type)
   219  			assert.EqualValues(t, []interface{}{1, "rsq", "qaz"}, param.Enum, "%s enum values are incorrect", param.Name)
   220  		case "foo_slice":
   221  			assert.Equal(t, "a FooSlice has foos which are strings", param.Description)
   222  			assert.Equal(t, "FooSlice", param.Extensions["x-go-name"])
   223  			assert.Equal(t, "query", param.In)
   224  			assert.Equal(t, "array", param.Type)
   225  			assert.False(t, param.Required)
   226  			assert.True(t, param.UniqueItems)
   227  			assert.Equal(t, "pipe", param.CollectionFormat)
   228  			assert.EqualValues(t, 3, *param.MinItems, "'foo_slice' should have had 3 min items")
   229  			assert.EqualValues(t, 10, *param.MaxItems, "'foo_slice' should have had 10 max items")
   230  			itprop := param.Items
   231  			assert.EqualValues(t, 3, *itprop.MinLength, "'foo_slice.items.minLength' should have been 3")
   232  			assert.EqualValues(t, 10, *itprop.MaxLength, "'foo_slice.items.maxLength' should have been 10")
   233  			assert.EqualValues(t, "\\w+", itprop.Pattern, "'foo_slice.items.pattern' should have \\w+")
   234  			assert.EqualValues(t, "bar", itprop.Default, "'foo_slice.items.default' should have bar default value")
   235  
   236  		case "items":
   237  			assert.Equal(t, "Items", param.Extensions["x-go-name"])
   238  			assert.Equal(t, "body", param.In)
   239  			assert.NotNil(t, param.Schema)
   240  			aprop := param.Schema
   241  			assert.Equal(t, "array", aprop.Type[0])
   242  			assert.NotNil(t, aprop.Items)
   243  			assert.NotNil(t, aprop.Items.Schema)
   244  			itprop := aprop.Items.Schema
   245  			assert.Len(t, itprop.Properties, 4)
   246  			assert.Len(t, itprop.Required, 3)
   247  			assertProperty(t, itprop, "integer", "id", "int32", "ID")
   248  			iprop, ok := itprop.Properties["id"]
   249  			assert.True(t, ok)
   250  			assert.Equal(t, "ID of this no model instance.\nids in this application start at 11 and are smaller than 1000", iprop.Description)
   251  			assert.EqualValues(t, 1000, *iprop.Maximum)
   252  			assert.True(t, iprop.ExclusiveMaximum, "'id' should have had an exclusive maximum")
   253  			assert.NotNil(t, iprop.Minimum)
   254  			assert.EqualValues(t, 10, *iprop.Minimum)
   255  			assert.True(t, iprop.ExclusiveMinimum, "'id' should have had an exclusive minimum")
   256  			assert.Equal(t, 3, iprop.Default, "Items.ID default value is incorrect")
   257  
   258  			assertRef(t, itprop, "pet", "Pet", "#/definitions/pet")
   259  			iprop, ok = itprop.Properties["pet"]
   260  			assert.True(t, ok)
   261  			// if itprop.Ref.String() == "" {
   262  			// 	assert.Equal(t, "The Pet to add to this NoModel items bucket.\nPets can appear more than once in the bucket", iprop.Description)
   263  			// }
   264  
   265  			assertProperty(t, itprop, "integer", "quantity", "int16", "Quantity")
   266  			iprop, ok = itprop.Properties["quantity"]
   267  			assert.True(t, ok)
   268  			assert.Equal(t, "The amount of pets to add to this bucket.", iprop.Description)
   269  			assert.EqualValues(t, 1, *iprop.Minimum)
   270  			assert.EqualValues(t, 10, *iprop.Maximum)
   271  
   272  			assertProperty(t, itprop, "string", "notes", "", "Notes")
   273  			iprop, ok = itprop.Properties["notes"]
   274  			assert.True(t, ok)
   275  			assert.Equal(t, "Notes to add to this item.\nThis can be used to add special instructions.", iprop.Description)
   276  
   277  		case "bar_slice":
   278  			assert.Equal(t, "a BarSlice has bars which are strings", param.Description)
   279  			assert.Equal(t, "BarSlice", param.Extensions["x-go-name"])
   280  			assert.Equal(t, "query", param.In)
   281  			assert.Equal(t, "array", param.Type)
   282  			assert.False(t, param.Required)
   283  			assert.True(t, param.UniqueItems)
   284  			assert.Equal(t, "pipe", param.CollectionFormat)
   285  			assert.NotNil(t, param.Items, "bar_slice should have had an items property")
   286  			assert.EqualValues(t, 3, *param.MinItems, "'bar_slice' should have had 3 min items")
   287  			assert.EqualValues(t, 10, *param.MaxItems, "'bar_slice' should have had 10 max items")
   288  			itprop := param.Items
   289  			if assert.NotNil(t, itprop) {
   290  				assert.EqualValues(t, 4, *itprop.MinItems, "'bar_slice.items.minItems' should have been 4")
   291  				assert.EqualValues(t, 9, *itprop.MaxItems, "'bar_slice.items.maxItems' should have been 9")
   292  				itprop2 := itprop.Items
   293  				if assert.NotNil(t, itprop2) {
   294  					assert.EqualValues(t, 5, *itprop2.MinItems, "'bar_slice.items.items.minItems' should have been 5")
   295  					assert.EqualValues(t, 8, *itprop2.MaxItems, "'bar_slice.items.items.maxItems' should have been 8")
   296  					itprop3 := itprop2.Items
   297  					if assert.NotNil(t, itprop3) {
   298  						assert.EqualValues(t, 3, *itprop3.MinLength, "'bar_slice.items.items.items.minLength' should have been 3")
   299  						assert.EqualValues(t, 10, *itprop3.MaxLength, "'bar_slice.items.items.items.maxLength' should have been 10")
   300  						assert.EqualValues(t, "\\w+", itprop3.Pattern, "'bar_slice.items.items.items.pattern' should have \\w+")
   301  					}
   302  				}
   303  			}
   304  
   305  		default:
   306  			assert.Fail(t, "unknown property: "+param.Name)
   307  		}
   308  	}
   309  
   310  	// assert that the order of the parameters is maintained
   311  	order, ok := operations["anotherOperation"]
   312  	assert.True(t, ok)
   313  	assert.Len(t, order.Parameters, 12)
   314  
   315  	for index, param := range order.Parameters {
   316  		switch param.Name {
   317  		case "id":
   318  			assert.Equal(t, 0, index, "%s index incorrect", param.Name)
   319  		case "score":
   320  			assert.Equal(t, 1, index, "%s index incorrect", param.Name)
   321  		case "x-hdr-name":
   322  			assert.Equal(t, 2, index, "%s index incorrect", param.Name)
   323  		case "created":
   324  			assert.Equal(t, 3, index, "%s index incorrect", param.Name)
   325  		case "category_old":
   326  			assert.Equal(t, 4, index, "%s index incorrect", param.Name)
   327  		case "category":
   328  			assert.Equal(t, 5, index, "%s index incorrect", param.Name)
   329  		case "type_old":
   330  			assert.Equal(t, 6, index, "%s index incorrect", param.Name)
   331  		case "type":
   332  			assert.Equal(t, 7, index, "%s index incorrect", param.Name)
   333  		case gcBadEnum:
   334  			assert.Equal(t, 8, index, "%s index incorrect", param.Name)
   335  		case "foo_slice":
   336  			assert.Equal(t, 9, index, "%s index incorrect", param.Name)
   337  		case "bar_slice":
   338  			assert.Equal(t, 10, index, "%s index incorrect", param.Name)
   339  		case "items":
   340  			assert.Equal(t, 11, index, "%s index incorrect", param.Name)
   341  		default:
   342  			assert.Fail(t, "unknown property: "+param.Name)
   343  		}
   344  	}
   345  
   346  	// check that aliases work correctly
   347  	aliasOp, ok := operations["someAliasOperation"]
   348  	assert.True(t, ok)
   349  	assert.Len(t, aliasOp.Parameters, 4)
   350  	for _, param := range aliasOp.Parameters {
   351  		switch param.Name {
   352  		case "intAlias":
   353  			assert.Equal(t, "query", param.In)
   354  			assert.Equal(t, "integer", param.Type)
   355  			assert.Equal(t, "int64", param.Format)
   356  			assert.True(t, param.Required)
   357  			assert.EqualValues(t, 10, *param.Maximum)
   358  			assert.EqualValues(t, 1, *param.Minimum)
   359  		case "stringAlias":
   360  			assert.Equal(t, "query", param.In)
   361  			assert.Equal(t, "string", param.Type)
   362  		case "intAliasPath":
   363  			assert.Equal(t, "path", param.In)
   364  			assert.Equal(t, "integer", param.Type)
   365  			assert.Equal(t, "int64", param.Format)
   366  		case "intAliasForm":
   367  			assert.Equal(t, "formData", param.In)
   368  			assert.Equal(t, "integer", param.Type)
   369  			assert.Equal(t, "int64", param.Format)
   370  		default:
   371  			assert.Fail(t, "unknown property: "+param.Name)
   372  		}
   373  	}
   374  }
   375  
   376  func TestParameterParser_Issue2007(t *testing.T) {
   377  	sctx := loadClassificationPkgsCtx(t)
   378  	operations := make(map[string]*spec.Operation)
   379  	td := getParameter(sctx, "SetConfiguration")
   380  	prs := &parameterBuilder{
   381  		ctx:  sctx,
   382  		decl: td,
   383  	}
   384  	require.NoError(t, prs.Build(operations))
   385  
   386  	op := operations["getConfiguration"]
   387  	require.NotNil(t, op)
   388  	require.Len(t, op.Parameters, 1)
   389  	sch := op.Parameters[0].Schema
   390  	require.NotNil(t, sch)
   391  
   392  	require.True(t, sch.Type.Contains("object"))
   393  	require.NotNil(t, sch.AdditionalProperties)
   394  	require.NotNil(t, sch.AdditionalProperties.Schema)
   395  	require.True(t, sch.AdditionalProperties.Schema.Type.Contains("string"))
   396  }
   397  
   398  func TestParameterParser_Issue2011(t *testing.T) {
   399  	sctx := loadClassificationPkgsCtx(t)
   400  	operations := make(map[string]*spec.Operation)
   401  	td := getParameter(sctx, "NumPlates")
   402  	prs := &parameterBuilder{
   403  		ctx:  sctx,
   404  		decl: td,
   405  	}
   406  	require.NoError(t, prs.Build(operations))
   407  
   408  	op := operations["putNumPlate"]
   409  	require.NotNil(t, op)
   410  	require.Len(t, op.Parameters, 1)
   411  	sch := op.Parameters[0].Schema
   412  	require.NotNil(t, sch)
   413  }