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