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  }