github.com/Kartograf/gqlgen@v0.7.2/codegen/util_test.go (about) 1 package codegen 2 3 import ( 4 "go/ast" 5 "go/importer" 6 "go/parser" 7 "go/token" 8 "go/types" 9 "testing" 10 11 "github.com/stretchr/testify/require" 12 ) 13 14 func TestNormalizeVendor(t *testing.T) { 15 require.Equal(t, "bar/baz", normalizeVendor("foo/vendor/bar/baz")) 16 require.Equal(t, "[]bar/baz", normalizeVendor("[]foo/vendor/bar/baz")) 17 require.Equal(t, "*bar/baz", normalizeVendor("*foo/vendor/bar/baz")) 18 require.Equal(t, "*[]*bar/baz", normalizeVendor("*[]*foo/vendor/bar/baz")) 19 require.Equal(t, "[]*bar/baz", normalizeVendor("[]*foo/vendor/bar/baz")) 20 } 21 22 func TestFindField(t *testing.T) { 23 input := ` 24 package test 25 26 type Std struct { 27 Name string 28 Value int 29 } 30 type Anon struct { 31 Name string 32 Tags 33 } 34 type Tags struct { 35 Bar string ` + "`" + `gqlgen:"foo"` + "`" + ` 36 Foo int ` + "`" + `gqlgen:"bar"` + "`" + ` 37 } 38 type Amb struct { 39 Bar string ` + "`" + `gqlgen:"foo"` + "`" + ` 40 Foo int ` + "`" + `gqlgen:"foo"` + "`" + ` 41 } 42 type Embed struct { 43 Std 44 Test string 45 } 46 ` 47 scope, err := parseScope(t, input, "test") 48 require.NoError(t, err) 49 50 std := scope.Lookup("Std").Type().Underlying().(*types.Struct) 51 anon := scope.Lookup("Anon").Type().Underlying().(*types.Struct) 52 tags := scope.Lookup("Tags").Type().Underlying().(*types.Struct) 53 amb := scope.Lookup("Amb").Type().Underlying().(*types.Struct) 54 embed := scope.Lookup("Embed").Type().Underlying().(*types.Struct) 55 56 tests := []struct { 57 Name string 58 Struct *types.Struct 59 Field string 60 Tag string 61 Expected string 62 ShouldError bool 63 }{ 64 {"Finds a field by name with no tag", std, "name", "", "Name", false}, 65 {"Finds a field by name when passed tag but tag not used", std, "name", "gqlgen", "Name", false}, 66 {"Ignores tags when not passed a tag", tags, "foo", "", "Foo", false}, 67 {"Picks field with tag over field name when passed a tag", tags, "foo", "gqlgen", "Bar", false}, 68 {"Errors when ambigious", amb, "foo", "gqlgen", "", true}, 69 {"Finds a field that is in embedded struct", anon, "bar", "", "Bar", false}, 70 {"Finds field that is not in embedded struct", embed, "test", "", "Test", false}, 71 } 72 73 for _, tt := range tests { 74 tt := tt 75 field, err := findField(tt.Struct, tt.Field, tt.Tag) 76 if tt.ShouldError { 77 require.Nil(t, field, tt.Name) 78 require.Error(t, err, tt.Name) 79 } else { 80 require.NoError(t, err, tt.Name) 81 require.Equal(t, tt.Expected, field.Name(), tt.Name) 82 } 83 } 84 } 85 86 func parseScope(t *testing.T, input interface{}, packageName string) (*types.Scope, error) { 87 // test setup to parse the types 88 fset := token.NewFileSet() 89 f, err := parser.ParseFile(fset, "test.go", input, 0) 90 if err != nil { 91 return nil, err 92 } 93 94 conf := types.Config{Importer: importer.Default()} 95 pkg, err := conf.Check(packageName, fset, []*ast.File{f}, nil) 96 if err != nil { 97 return nil, err 98 } 99 100 return pkg.Scope(), nil 101 } 102 103 func TestEqualFieldName(t *testing.T) { 104 tt := []struct { 105 Name string 106 Source string 107 Target string 108 Expected bool 109 }{ 110 {Name: "words with same case", Source: "test", Target: "test", Expected: true}, 111 {Name: "words different case", Source: "test", Target: "tEsT", Expected: true}, 112 {Name: "different words", Source: "foo", Target: "bar", Expected: false}, 113 {Name: "separated with underscore", Source: "the_test", Target: "TheTest", Expected: true}, 114 {Name: "empty values", Source: "", Target: "", Expected: true}, 115 } 116 117 for _, tc := range tt { 118 t.Run(tc.Name, func(t *testing.T) { 119 result := equalFieldName(tc.Source, tc.Target) 120 require.Equal(t, tc.Expected, result) 121 }) 122 } 123 } 124 125 func TestEqualTypes(t *testing.T) { 126 tt := []struct { 127 Name string 128 Source string 129 Target string 130 Expected bool 131 }{ 132 {Name: "basic", Source: "bar/baz", Target: "bar/baz", Expected: true}, 133 {Name: "basic slice", Source: "[]bar/baz", Target: "[]bar/baz", Expected: true}, 134 {Name: "pointer", Source: "*bar/baz", Target: "bar/baz", Expected: true}, 135 {Name: "pointer slice", Source: "[]*bar/baz", Target: "[]bar/baz", Expected: true}, 136 } 137 138 for _, tc := range tt { 139 t.Run(tc.Name, func(t *testing.T) { 140 result := equalTypes(tc.Source, tc.Target) 141 require.Equal(t, tc.Expected, result) 142 }) 143 } 144 }