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