Skip to content

Commit

Permalink
Add some more tests for config validation, and fix some gaps
Browse files Browse the repository at this point in the history
I set these tests up in #270, but I realized there's a lot more we could
test unrelated to that PR. In this commit I add some more tests. They're
not really exhaustive yet, but they did catch a few bugs, which I fixed:
- we weren't validating the package-name if you do set it (only if we
  guess it)
- If you omitted `generated`, you would try to write generated code to
  the directory containing `genqlient.yaml`, which makes no sense; now
  we default to `generated.go`. In the real world it's probably good to
  set explicitly, but it's actually very convenient in tests that we
  don't have to, and maybe in small projects too.
  • Loading branch information
benjaminjkraft committed May 7, 2023
1 parent ff790e1 commit cbdaff8
Show file tree
Hide file tree
Showing 18 changed files with 141 additions and 30 deletions.
3 changes: 1 addition & 2 deletions docs/genqlient.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ operations:
- "pkg/*.go"

# The filename to which to write the generated code, relative to
# genqlient.yaml.
# genqlient.yaml. Default: generated.go.
generated: generated/genqlient.go

# The package name for the output code; defaults to the directory name of
Expand Down Expand Up @@ -77,7 +77,6 @@ context_type: context.Context
# without making a query.
client_getter: "github.com/you/yourpkg.GetClient"


# If set, fields with a struct type will default to having
# the "pointer: true, omitempty: true" flag.
#
Expand Down
15 changes: 12 additions & 3 deletions generate/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ func (c *Config) ValidateAndFillDefaults(baseDir string) error {
for i := range c.Operations {
c.Operations[i] = pathJoin(baseDir, c.Operations[i])
}
if c.Generated == "" {
c.Generated = "generated.go"
}
c.Generated = pathJoin(baseDir, c.Generated)
if c.ExportOperations != "" {
c.ExportOperations = pathJoin(baseDir, c.ExportOperations)
Expand All @@ -164,17 +167,23 @@ func (c *Config) ValidateAndFillDefaults(baseDir string) error {
"\nExample: \"github.com/Org/Repo/optional.Value\"")
}

if c.Package == "" {
if c.Package != "" {
if !token.IsIdentifier(c.Package) {
// No need for link here -- if you're already setting the package
// you know where to set the package.
return errorf(nil, "invalid package in genqlient.yaml: '%v' is not a valid identifier", c.Package)
}
} else {
abs, err := filepath.Abs(c.Generated)
if err != nil {
return errorf(nil, "unable to guess package-name: %v is not a valid identifier"+
return errorf(nil, "unable to guess package-name: %v"+
"\nSet package name in genqlient.yaml"+
"\nExample: https://github.com/Khan/genqlient/blob/main/example/genqlient.yaml#L6", err)
}

base := filepath.Base(filepath.Dir(abs))
if !token.IsIdentifier(base) {
return errorf(nil, "unable to guess package-name: %v is not a valid identifier"+
return errorf(nil, "unable to guess package-name: '%v' is not a valid identifier"+
"\nSet package name in genqlient.yaml"+
"\nExample: https://github.com/Khan/genqlient/blob/main/example/genqlient.yaml#L6", base)
}
Expand Down
37 changes: 30 additions & 7 deletions generate/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

const (
findConfigDir = "testdata/find-config"
validConfigDir = "testdata/valid-config"
invalidConfigDir = "testdata/invalid-config"
)

Expand Down Expand Up @@ -114,18 +115,40 @@ func TestAbsoluteAndRelativePathsInConfigFiles(t *testing.T) {
require.Equal(t, "/tmp/genqlient.graphql", config.Operations[0])
}

func TestInvalidConfigs(t *testing.T) {
files, err := os.ReadDir(invalidConfigDir)
func testAllSnapshots(
t *testing.T,
dir string,
testfunc func(t *testing.T, filename string),
) {
files, err := os.ReadDir(dir)
if err != nil {
t.Fatal(err)
}

for _, file := range files {
t.Run(file.Name(), func(t *testing.T) {
filename := filepath.Join(invalidConfigDir, file.Name())
_, err := ReadAndValidateConfig(filename)
require.Error(t, err)
testutil.Cupaloy.SnapshotT(t, err.Error())
name := file.Name()
if name[0] == '.' {
continue // editor backup files, etc.
}
t.Run(name, func(t *testing.T) {
filename := filepath.Join(dir, file.Name())
testfunc(t, filename)
})
}
}

func TestValidConfigs(t *testing.T) {
testAllSnapshots(t, validConfigDir, func(t *testing.T, filename string) {
config, err := ReadAndValidateConfig(filename)
require.NoError(t, err)
testutil.Cupaloy.SnapshotT(t, config)
})
}

func TestInvalidConfigs(t *testing.T) {
testAllSnapshots(t, invalidConfigDir, func(t *testing.T, filename string) {
_, err := ReadAndValidateConfig(filename)
require.Error(t, err)
testutil.Cupaloy.SnapshotT(t, err.Error())
})
}
19 changes: 2 additions & 17 deletions generate/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,20 +164,16 @@ func TestGenerateWithConfig(t *testing.T) {
Package: "mypkg",
}},
{"ExportOperations", "", nil, &Config{
Generated: "generated.go",
ExportOperations: "operations.json",
}},
{"CustomContext", "", nil, &Config{
Generated: "generated.go",
ContextType: "github.com/Khan/genqlient/internal/testutil.MyContext",
}},
{"CustomContextWithAlias", "", nil, &Config{
Generated: "generated.go",
ContextType: "github.com/Khan/genqlient/internal/testutil/junk---fun.name.MyContext",
}},
{"StructReferences", "", []string{"InputObject.graphql", "QueryWithStructs.graphql"}, &Config{
StructReferences: true,
Generated: "generated.go",
Bindings: map[string]*TypeBinding{
"Date": {
Type: "time.Time",
Expand All @@ -189,7 +185,6 @@ func TestGenerateWithConfig(t *testing.T) {
{"StructReferencesAndOptionalPointer", "", []string{"InputObject.graphql", "QueryWithStructs.graphql"}, &Config{
StructReferences: true,
Optional: "pointer",
Generated: "generated.go",
Bindings: map[string]*TypeBinding{
"Date": {
Type: "time.Time",
Expand All @@ -204,48 +199,38 @@ func TestGenerateWithConfig(t *testing.T) {
},
}},
{"NoContext", "", nil, &Config{
Generated: "generated.go",
ContextType: "-",
}},
{"ClientGetter", "", nil, &Config{
Generated: "generated.go",
ClientGetter: "github.com/Khan/genqlient/internal/testutil.GetClientFromContext",
}},
{"ClientGetterCustomContext", "", nil, &Config{
Generated: "generated.go",
ClientGetter: "github.com/Khan/genqlient/internal/testutil.GetClientFromMyContext",
ContextType: "github.com/Khan/genqlient/internal/testutil.MyContext",
}},
{"ClientGetterNoContext", "", nil, &Config{
Generated: "generated.go",
ClientGetter: "github.com/Khan/genqlient/internal/testutil.GetClientFromNowhere",
ContextType: "-",
}},
{"Extensions", "", nil, &Config{
Generated: "generated.go",
Extensions: true,
}},
{"OptionalValue", "", []string{"ListInput.graphql", "QueryWithSlices.graphql"}, &Config{
Generated: "generated.go",
Optional: "value",
Optional: "value",
}},
{"OptionalPointer", "", []string{"ListInput.graphql", "QueryWithSlices.graphql"}, &Config{
Generated: "generated.go",
Optional: "pointer",
Optional: "pointer",
}},
{"OptionalGeneric", "", []string{"ListInput.graphql", "QueryWithSlices.graphql"}, &Config{
Generated: "generated.go",
Optional: "generic",
OptionalGenericType: "github.com/Khan/genqlient/internal/testutil.Option",
}},
{"EnumRawCasingAll", "", []string{"QueryWithEnums.graphql"}, &Config{
Generated: "generated.go",
Casing: Casing{
AllEnums: CasingRaw,
},
}},
{"EnumRawCasingSpecific", "", []string{"QueryWithEnums.graphql"}, &Config{
Generated: "generated.go",
Casing: Casing{
Enums: map[string]CasingAlgorithm{"Role": CasingRaw},
},
Expand Down
Empty file.
1 change: 1 addition & 0 deletions generate/testdata/invalid-config/InvalidCasing.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
package: invalidConfig
casing:
enums:
MyType: bogus
2 changes: 2 additions & 0 deletions generate/testdata/invalid-config/InvalidOptional.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
package: invalidConfig
optional: bogus
1 change: 1 addition & 0 deletions generate/testdata/invalid-config/InvalidPackage.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package: bogus-package-name

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
invalid config file testdata/invalid-config/CantGuessPackage.yaml: unable to guess package-name: 'invalid-config' is not a valid identifier
Set package name in genqlient.yaml
Example: https://github.com/Khan/genqlient/blob/main/example/genqlient.yaml#L6
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
invalid config file testdata/invalid-config/InvalidOptional.yaml: optional must be one of: 'value' (default), 'pointer', or 'generic'
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
invalid config file testdata/invalid-config/InvalidPackage.yaml: invalid package in genqlient.yaml: 'bogus-package-name' is not a valid identifier
27 changes: 27 additions & 0 deletions generate/testdata/snapshots/TestValidConfigs-Lists.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
(*generate.Config)({
Schema: (generate.StringList) (len=2) {
(string) (len=42) "testdata/valid-config/first_schema.graphql",
(string) (len=43) "testdata/valid-config/second_schema.graphql"
},
Operations: (generate.StringList) (len=2) {
(string) (len=46) "testdata/valid-config/first_operations.graphql",
(string) (len=47) "testdata/valid-config/second_operations.graphql"
},
Generated: (string) (len=34) "testdata/valid-config/generated.go",
Package: (string) (len=11) "validConfig",
ExportOperations: (string) "",
ContextType: (string) (len=15) "context.Context",
ClientGetter: (string) "",
Bindings: (map[string]*generate.TypeBinding) <nil>,
PackageBindings: ([]*generate.PackageBinding) <nil>,
Casing: (generate.Casing) {
AllEnums: (generate.CasingAlgorithm) "",
Enums: (map[string]generate.CasingAlgorithm) <nil>
},
Optional: (string) "",
OptionalGenericType: (string) "",
StructReferences: (bool) false,
Extensions: (bool) false,
AllowBrokenFeatures: (bool) false,
baseDir: (string) (len=21) "testdata/valid-config"
})
21 changes: 21 additions & 0 deletions generate/testdata/snapshots/TestValidConfigs-Simple.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
(*generate.Config)({
Schema: (generate.StringList) <nil>,
Operations: (generate.StringList) <nil>,
Generated: (string) (len=34) "testdata/valid-config/generated.go",
Package: (string) (len=11) "validConfig",
ExportOperations: (string) "",
ContextType: (string) (len=15) "context.Context",
ClientGetter: (string) "",
Bindings: (map[string]*generate.TypeBinding) <nil>,
PackageBindings: ([]*generate.PackageBinding) <nil>,
Casing: (generate.Casing) {
AllEnums: (generate.CasingAlgorithm) "",
Enums: (map[string]generate.CasingAlgorithm) <nil>
},
Optional: (string) "",
OptionalGenericType: (string) "",
StructReferences: (bool) false,
Extensions: (bool) false,
AllowBrokenFeatures: (bool) false,
baseDir: (string) (len=21) "testdata/valid-config"
})
25 changes: 25 additions & 0 deletions generate/testdata/snapshots/TestValidConfigs-Strings.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
(*generate.Config)({
Schema: (generate.StringList) (len=1) {
(string) (len=36) "testdata/valid-config/schema.graphql"
},
Operations: (generate.StringList) (len=1) {
(string) (len=40) "testdata/valid-config/operations.graphql"
},
Generated: (string) (len=34) "testdata/valid-config/generated.go",
Package: (string) (len=11) "validConfig",
ExportOperations: (string) "",
ContextType: (string) (len=15) "context.Context",
ClientGetter: (string) "",
Bindings: (map[string]*generate.TypeBinding) <nil>,
PackageBindings: ([]*generate.PackageBinding) <nil>,
Casing: (generate.Casing) {
AllEnums: (generate.CasingAlgorithm) "",
Enums: (map[string]generate.CasingAlgorithm) <nil>
},
Optional: (string) "",
OptionalGenericType: (string) "",
StructReferences: (bool) false,
Extensions: (bool) false,
AllowBrokenFeatures: (bool) false,
baseDir: (string) (len=21) "testdata/valid-config"
})
9 changes: 9 additions & 0 deletions generate/testdata/valid-config/Lists.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
schema:
- first_schema.graphql
- second_schema.graphql

operations:
- first_operations.graphql
- second_operations.graphql

package: validConfig
1 change: 1 addition & 0 deletions generate/testdata/valid-config/Simple.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package: validConfig
3 changes: 3 additions & 0 deletions generate/testdata/valid-config/Strings.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
schema: schema.graphql
operations: operations.graphql
package: validConfig

0 comments on commit cbdaff8

Please sign in to comment.