github.com/kerryoscer/gqlgen@v0.17.29/codegen/config/config_test.go (about) 1 package config 2 3 import ( 4 "errors" 5 "io/fs" 6 "os" 7 "path/filepath" 8 "runtime" 9 "testing" 10 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 "github.com/vektah/gqlparser/v2/ast" 14 15 "github.com/kerryoscer/gqlgen/internal/code" 16 ) 17 18 func TestLoadConfig(t *testing.T) { 19 t.Run("config does not exist", func(t *testing.T) { 20 _, err := LoadConfig("doesnotexist.yml") 21 require.Error(t, err) 22 }) 23 24 t.Run("malformed config", func(t *testing.T) { 25 _, err := LoadConfig("testdata/cfg/malformedconfig.yml") 26 require.EqualError(t, err, "unable to parse config: yaml: unmarshal errors:\n line 1: cannot unmarshal !!str `asdf` into config.Config") 27 }) 28 29 t.Run("unknown keys", func(t *testing.T) { 30 _, err := LoadConfig("testdata/cfg/unknownkeys.yml") 31 require.EqualError(t, err, "unable to parse config: yaml: unmarshal errors:\n line 2: field unknown not found in type config.Config") 32 }) 33 34 t.Run("globbed filenames", func(t *testing.T) { 35 c, err := LoadConfig("testdata/cfg/glob.yml") 36 require.NoError(t, err) 37 38 if runtime.GOOS == "windows" { 39 require.Equal(t, c.SchemaFilename[0], `testdata\cfg\glob\bar\bar with spaces.graphql`) 40 require.Equal(t, c.SchemaFilename[1], `testdata\cfg\glob\foo\foo.graphql`) 41 } else { 42 require.Equal(t, c.SchemaFilename[0], "testdata/cfg/glob/bar/bar with spaces.graphql") 43 require.Equal(t, c.SchemaFilename[1], "testdata/cfg/glob/foo/foo.graphql") 44 } 45 }) 46 47 t.Run("unwalkable path", func(t *testing.T) { 48 _, err := LoadConfig("testdata/cfg/unwalkable.yml") 49 if runtime.GOOS == "windows" { 50 require.EqualError(t, err, "failed to walk schema at root not_walkable/: CreateFile not_walkable/: The system cannot find the file specified.") 51 } else { 52 require.EqualError(t, err, "failed to walk schema at root not_walkable/: lstat not_walkable/: no such file or directory") 53 } 54 }) 55 } 56 57 func TestLoadConfigFromDefaultLocation(t *testing.T) { 58 testDir, err := os.Getwd() 59 require.NoError(t, err) 60 var cfg *Config 61 62 t.Run("will find closest match", func(t *testing.T) { 63 err = os.Chdir(filepath.Join(testDir, "testdata", "cfg", "subdir")) 64 require.NoError(t, err) 65 66 cfg, err = LoadConfigFromDefaultLocations() 67 require.NoError(t, err) 68 require.Equal(t, StringList{"inner"}, cfg.SchemaFilename) 69 }) 70 71 t.Run("will find config in parent dirs", func(t *testing.T) { 72 err = os.Chdir(filepath.Join(testDir, "testdata", "cfg", "otherdir")) 73 require.NoError(t, err) 74 75 cfg, err = LoadConfigFromDefaultLocations() 76 require.NoError(t, err) 77 require.Equal(t, StringList{"outer"}, cfg.SchemaFilename) 78 }) 79 80 t.Run("will return error if config doesn't exist", func(t *testing.T) { 81 err = os.Chdir(testDir) 82 require.NoError(t, err) 83 84 cfg, err = LoadConfigFromDefaultLocations() 85 require.True(t, errors.Is(err, fs.ErrNotExist)) 86 }) 87 } 88 89 func TestLoadDefaultConfig(t *testing.T) { 90 testDir, err := os.Getwd() 91 require.NoError(t, err) 92 var cfg *Config 93 94 t.Run("will find the schema", func(t *testing.T) { 95 err = os.Chdir(filepath.Join(testDir, "testdata", "defaultconfig")) 96 require.NoError(t, err) 97 98 cfg, err = LoadDefaultConfig() 99 require.NoError(t, err) 100 require.NotEmpty(t, cfg.Sources) 101 }) 102 103 t.Run("will return error if schema doesn't exist", func(t *testing.T) { 104 err = os.Chdir(testDir) 105 require.NoError(t, err) 106 107 cfg, err = LoadDefaultConfig() 108 require.True(t, errors.Is(err, fs.ErrNotExist)) 109 }) 110 } 111 112 func TestReferencedPackages(t *testing.T) { 113 t.Run("valid", func(t *testing.T) { 114 tm := TypeMap{ 115 "Foo": {Model: StringList{"github.com/test.Foo"}}, 116 "Bar": {Model: StringList{"github.com/test.Bar"}}, 117 "Baz": {Model: StringList{"github.com/otherpkg.Baz"}}, 118 "Map": {Model: StringList{"map[string]interface{}"}}, 119 "SkipResolver": { 120 Fields: map[string]TypeMapField{ 121 "field": {Resolver: false}, 122 }, 123 }, 124 } 125 126 pkgs := tm.ReferencedPackages() 127 128 assert.Equal(t, []string{"github.com/test", "github.com/otherpkg"}, pkgs) 129 }) 130 } 131 132 func TestConfigCheck(t *testing.T) { 133 for _, execLayout := range []ExecLayout{ExecLayoutSingleFile, ExecLayoutFollowSchema} { 134 t.Run(string(execLayout), func(t *testing.T) { 135 t.Run("invalid config format due to conflicting package names", func(t *testing.T) { 136 config := Config{ 137 Exec: ExecConfig{Layout: execLayout, Filename: "generated/exec.go", DirName: "generated", Package: "graphql"}, 138 Model: PackageConfig{Filename: "generated/models.go"}, 139 } 140 141 require.EqualError(t, config.check(), "exec and model define the same import path (github.com/99designs/gqlgen/codegen/config/generated) with different package names (graphql vs generated)") 142 }) 143 144 t.Run("federation must be in exec package", func(t *testing.T) { 145 config := Config{ 146 Exec: ExecConfig{Layout: execLayout, Filename: "generated/exec.go", DirName: "generated"}, 147 Federation: PackageConfig{Filename: "anotherpkg/federation.go"}, 148 } 149 150 require.EqualError(t, config.check(), "federation and exec must be in the same package") 151 }) 152 153 t.Run("federation must have same package name as exec", func(t *testing.T) { 154 config := Config{ 155 Exec: ExecConfig{Layout: execLayout, Filename: "generated/exec.go", DirName: "generated"}, 156 Federation: PackageConfig{Filename: "generated/federation.go", Package: "federation"}, 157 } 158 159 require.EqualError(t, config.check(), "exec and federation define the same import path (github.com/99designs/gqlgen/codegen/config/generated) with different package names (generated vs federation)") 160 }) 161 162 t.Run("deprecated federated flag raises an error", func(t *testing.T) { 163 config := Config{ 164 Exec: ExecConfig{Layout: execLayout, Filename: "generated/exec.go", DirName: "generated"}, 165 Federated: true, 166 } 167 168 require.EqualError(t, config.check(), "federated has been removed, instead use\nfederation:\n filename: path/to/federated.go") 169 }) 170 }) 171 } 172 } 173 174 func TestAutobinding(t *testing.T) { 175 t.Run("valid paths", func(t *testing.T) { 176 cfg := Config{ 177 Models: TypeMap{}, 178 AutoBind: []string{ 179 "github.com/kerryoscer/gqlgen/codegen/config/testdata/autobinding/chat", 180 "github.com/kerryoscer/gqlgen/codegen/config/testdata/autobinding/scalars/model", 181 }, 182 Packages: &code.Packages{}, 183 } 184 185 cfg.Schema = gqlparser.MustLoadSchema(&ast.Source{Name: "TestAutobinding.schema", Input: ` 186 scalar Banned 187 type Message { id: ID } 188 `}) 189 190 require.NoError(t, cfg.autobind()) 191 192 require.Equal(t, "github.com/kerryoscer/gqlgen/codegen/config/testdata/autobinding/scalars/model.Banned", cfg.Models["Banned"].Model[0]) 193 require.Equal(t, "github.com/kerryoscer/gqlgen/codegen/config/testdata/autobinding/chat.Message", cfg.Models["Message"].Model[0]) 194 }) 195 196 t.Run("with file path", func(t *testing.T) { 197 cfg := Config{ 198 Models: TypeMap{}, 199 AutoBind: []string{ 200 "../chat", 201 }, 202 Packages: &code.Packages{}, 203 } 204 205 cfg.Schema = gqlparser.MustLoadSchema(&ast.Source{Name: "TestAutobinding.schema", Input: ` 206 scalar Banned 207 type Message { id: ID } 208 `}) 209 210 require.EqualError(t, cfg.autobind(), "unable to load ../chat - make sure you're using an import path to a package that exists") 211 }) 212 }