github.com/geneva/gqlgen@v0.17.7-0.20230801155730-7b9317164836/plugin/federation/federation_test.go (about) 1 package federation 2 3 import ( 4 "testing" 5 6 "github.com/geneva/gqlgen/codegen" 7 "github.com/geneva/gqlgen/codegen/config" 8 "github.com/stretchr/testify/require" 9 ) 10 11 func TestWithEntities(t *testing.T) { 12 f, cfg := load(t, "testdata/allthethings/gqlgen.yml") 13 14 require.Equal(t, []string{"ExternalExtension", "Hello", "MoreNesting", "NestedKey", "VeryNestedKey", "World"}, cfg.Schema.Types["_Entity"].Types) 15 16 require.Len(t, cfg.Schema.Types["Entity"].Fields, 6) 17 18 require.Equal(t, "findExternalExtensionByUpc", cfg.Schema.Types["Entity"].Fields[0].Name) 19 require.Equal(t, "findHelloByName", cfg.Schema.Types["Entity"].Fields[1].Name) 20 // missing on purpose: all @external fields: 21 // require.Equal(t, "findMoreNestingByID", cfg.Schema.Types["Entity"].Fields[2].Name) 22 require.Equal(t, "findNestedKeyByIDAndHelloName", cfg.Schema.Types["Entity"].Fields[2].Name) 23 require.Equal(t, "findVeryNestedKeyByIDAndHelloNameAndWorldFooAndWorldBarAndMoreWorldFoo", cfg.Schema.Types["Entity"].Fields[3].Name) 24 require.Equal(t, "findWorldByFoo", cfg.Schema.Types["Entity"].Fields[4].Name) 25 require.Equal(t, "findWorldByBar", cfg.Schema.Types["Entity"].Fields[5].Name) 26 27 require.NoError(t, f.MutateConfig(cfg)) 28 29 require.Len(t, f.Entities, 6) 30 31 require.Equal(t, "ExternalExtension", f.Entities[0].Name) 32 require.Len(t, f.Entities[0].Resolvers, 1) 33 require.Len(t, f.Entities[0].Resolvers[0].KeyFields, 1) 34 require.Equal(t, "upc", f.Entities[0].Resolvers[0].KeyFields[0].Definition.Name) 35 require.Equal(t, "String", f.Entities[0].Resolvers[0].KeyFields[0].Definition.Type.Name()) 36 37 require.Equal(t, "Hello", f.Entities[1].Name) 38 require.Len(t, f.Entities[1].Resolvers, 1) 39 require.Len(t, f.Entities[1].Resolvers[0].KeyFields, 1) 40 require.Equal(t, "name", f.Entities[1].Resolvers[0].KeyFields[0].Definition.Name) 41 require.Equal(t, "String", f.Entities[1].Resolvers[0].KeyFields[0].Definition.Type.Name()) 42 43 require.Equal(t, "MoreNesting", f.Entities[2].Name) 44 require.Len(t, f.Entities[2].Resolvers, 0) 45 46 require.Equal(t, "NestedKey", f.Entities[3].Name) 47 require.Len(t, f.Entities[3].Resolvers, 1) 48 require.Len(t, f.Entities[3].Resolvers[0].KeyFields, 2) 49 require.Equal(t, "id", f.Entities[3].Resolvers[0].KeyFields[0].Definition.Name) 50 require.Equal(t, "String", f.Entities[3].Resolvers[0].KeyFields[0].Definition.Type.Name()) 51 require.Equal(t, "helloName", f.Entities[3].Resolvers[0].KeyFields[1].Definition.Name) 52 require.Equal(t, "String", f.Entities[3].Resolvers[0].KeyFields[1].Definition.Type.Name()) 53 54 require.Equal(t, "VeryNestedKey", f.Entities[4].Name) 55 require.Len(t, f.Entities[4].Resolvers, 1) 56 require.Len(t, f.Entities[4].Resolvers[0].KeyFields, 5) 57 require.Equal(t, "id", f.Entities[4].Resolvers[0].KeyFields[0].Definition.Name) 58 require.Equal(t, "String", f.Entities[4].Resolvers[0].KeyFields[0].Definition.Type.Name()) 59 require.Equal(t, "helloName", f.Entities[4].Resolvers[0].KeyFields[1].Definition.Name) 60 require.Equal(t, "String", f.Entities[4].Resolvers[0].KeyFields[1].Definition.Type.Name()) 61 require.Equal(t, "worldFoo", f.Entities[4].Resolvers[0].KeyFields[2].Definition.Name) 62 require.Equal(t, "String", f.Entities[4].Resolvers[0].KeyFields[2].Definition.Type.Name()) 63 require.Equal(t, "worldBar", f.Entities[4].Resolvers[0].KeyFields[3].Definition.Name) 64 require.Equal(t, "Int", f.Entities[4].Resolvers[0].KeyFields[3].Definition.Type.Name()) 65 require.Equal(t, "moreWorldFoo", f.Entities[4].Resolvers[0].KeyFields[4].Definition.Name) 66 require.Equal(t, "String", f.Entities[4].Resolvers[0].KeyFields[4].Definition.Type.Name()) 67 68 require.Len(t, f.Entities[4].Requires, 2) 69 require.Equal(t, f.Entities[4].Requires[0].Name, "id") 70 require.Equal(t, f.Entities[4].Requires[1].Name, "helloSecondary") 71 72 require.Equal(t, "World", f.Entities[5].Name) 73 require.Len(t, f.Entities[5].Resolvers, 2) 74 require.Len(t, f.Entities[5].Resolvers[0].KeyFields, 1) 75 require.Equal(t, "foo", f.Entities[5].Resolvers[0].KeyFields[0].Definition.Name) 76 require.Equal(t, "String", f.Entities[5].Resolvers[0].KeyFields[0].Definition.Type.Name()) 77 require.Len(t, f.Entities[5].Resolvers[1].KeyFields, 1) 78 require.Equal(t, "bar", f.Entities[5].Resolvers[1].KeyFields[0].Definition.Name) 79 require.Equal(t, "Int", f.Entities[5].Resolvers[1].KeyFields[0].Definition.Type.Name()) 80 } 81 82 func TestNoEntities(t *testing.T) { 83 f, cfg := load(t, "testdata/entities/nokey.yml") 84 85 err := f.MutateConfig(cfg) 86 require.NoError(t, err) 87 require.Len(t, f.Entities, 0) 88 } 89 90 func TestUnusedInterfaceKeyDirective(t *testing.T) { 91 f, cfg := load(t, "testdata/interfaces/unused_key.yml") 92 93 err := f.MutateConfig(cfg) 94 require.NoError(t, err) 95 require.Len(t, f.Entities, 0) 96 } 97 98 func TestInterfaceKeyDirective(t *testing.T) { 99 f, cfg := load(t, "testdata/interfaces/key.yml") 100 101 err := f.MutateConfig(cfg) 102 require.NoError(t, err) 103 require.Len(t, cfg.Schema.Types["_Entity"].Types, 1) 104 require.Len(t, f.Entities, 2) 105 } 106 107 func TestInterfaceExtendsDirective(t *testing.T) { 108 require.Panics(t, func() { 109 load(t, "testdata/interfaces/extends.yml") 110 }) 111 } 112 113 func TestCodeGeneration(t *testing.T) { 114 f, cfg := load(t, "testdata/allthethings/gqlgen.yml") 115 116 require.Len(t, cfg.Schema.Types["_Entity"].Types, 6) 117 require.Len(t, f.Entities, 6) 118 119 require.NoError(t, f.MutateConfig(cfg)) 120 121 data, err := codegen.BuildData(cfg) 122 if err != nil { 123 panic(err) 124 } 125 require.NoError(t, f.GenerateCode(data)) 126 } 127 128 func TestCodeGenerationFederation2(t *testing.T) { 129 f, cfg := load(t, "testdata/federation2/federation2.yml") 130 err := f.MutateConfig(cfg) 131 132 require.NoError(t, err) 133 require.Equal(t, "ExternalExtension", f.Entities[0].Name) 134 require.Len(t, f.Entities[0].Resolvers, 1) 135 require.Equal(t, "Hello", f.Entities[1].Name) 136 require.Empty(t, f.Entities[1].Resolvers) 137 require.Equal(t, "World", f.Entities[2].Name) 138 require.Empty(t, f.Entities[2].Resolvers) 139 140 data, err := codegen.BuildData(cfg) 141 if err != nil { 142 panic(err) 143 } 144 require.NoError(t, f.GenerateCode(data)) 145 } 146 147 func TestInjectSourceLate(t *testing.T) { 148 _, cfg := load(t, "testdata/allthethings/gqlgen.yml") 149 entityGraphqlGenerated := false 150 for _, source := range cfg.Sources { 151 if source.Name != "federation/entity.graphql" { 152 continue 153 } 154 entityGraphqlGenerated = true 155 require.Contains(t, source.Input, "union _Entity") 156 require.Contains(t, source.Input, "type _Service {") 157 require.Contains(t, source.Input, "extend type Query {") 158 require.Contains(t, source.Input, "_entities(representations: [_Any!]!): [_Entity]!") 159 require.Contains(t, source.Input, "_service: _Service!") 160 } 161 require.True(t, entityGraphqlGenerated) 162 163 _, cfg = load(t, "testdata/entities/nokey.yml") 164 entityGraphqlGenerated = false 165 for _, source := range cfg.Sources { 166 if source.Name != "federation/entity.graphql" { 167 continue 168 } 169 entityGraphqlGenerated = true 170 require.NotContains(t, source.Input, "union _Entity") 171 require.Contains(t, source.Input, "type _Service {") 172 require.Contains(t, source.Input, "extend type Query {") 173 require.NotContains(t, source.Input, "_entities(representations: [_Any!]!): [_Entity]!") 174 require.Contains(t, source.Input, "_service: _Service!") 175 } 176 require.True(t, entityGraphqlGenerated) 177 178 _, cfg = load(t, "testdata/schema/customquerytype.yml") 179 for _, source := range cfg.Sources { 180 if source.Name != "federation/entity.graphql" { 181 continue 182 } 183 require.Contains(t, source.Input, "extend type CustomQuery {") 184 } 185 } 186 187 func load(t *testing.T, name string) (*federation, *config.Config) { 188 t.Helper() 189 190 cfg, err := config.LoadConfig(name) 191 require.NoError(t, err) 192 193 if cfg.Federation.Version == 0 { 194 cfg.Federation.Version = 1 195 } 196 197 f := &federation{Version: cfg.Federation.Version} 198 cfg.Sources = append(cfg.Sources, f.InjectSourceEarly()) 199 require.NoError(t, cfg.LoadSchema()) 200 201 if src := f.InjectSourceLate(cfg.Schema); src != nil { 202 cfg.Sources = append(cfg.Sources, src) 203 } 204 require.NoError(t, cfg.LoadSchema()) 205 206 require.NoError(t, cfg.Init()) 207 return f, cfg 208 }