UNPKG

@apollo/federation

Version:
252 lines (236 loc) 6.04 kB
import { Kind, DocumentNode, GraphQLSchema, specifiedDirectives, } from 'graphql'; import { validateSDL } from 'graphql/validation/validate'; import { buildMapsFromServiceList } from '../../../compose'; import { astSerializer, typeSerializer, selectionSetSerializer, graphqlErrorSerializer, gql, } from 'apollo-federation-integration-testsuite'; import { knownSubgraphDirectives } from '@apollo/subgraph/dist/directives'; import { ServiceDefinition } from '../../../types'; import { MatchingEnums } from '../matchingEnums'; expect.addSnapshotSerializer(astSerializer); expect.addSnapshotSerializer(typeSerializer); expect.addSnapshotSerializer(selectionSetSerializer); expect.addSnapshotSerializer(graphqlErrorSerializer); // simulate the first half of the composition process const createDefinitionsDocumentForServices = ( serviceList: ServiceDefinition[], ): DocumentNode => { const { typeDefinitionsMap } = buildMapsFromServiceList(serviceList); return { kind: Kind.DOCUMENT, definitions: Object.values(typeDefinitionsMap).flat(), }; }; describe('matchingEnums', () => { let schema: GraphQLSchema; // create a blank schema for each test beforeEach(() => { schema = new GraphQLSchema({ query: undefined, directives: [...specifiedDirectives, ...knownSubgraphDirectives], }); }); it('does not error with matching enums across services', () => { const serviceList = [ { typeDefs: gql` enum ProductCategory { BED BATH } `, name: 'serviceA', }, { typeDefs: gql` enum ProductCategory { BED BATH } `, name: 'serviceB', }, ]; const definitionsDocument = createDefinitionsDocumentForServices( serviceList, ); const errors = validateSDL(definitionsDocument, schema, [MatchingEnums]); expect(errors).toHaveLength(0); }); it('errors when enums in separate services dont match', () => { const serviceList = [ { typeDefs: gql` enum ProductCategory { BED BATH } `, name: 'serviceA', }, { typeDefs: gql` enum ProductCategory { BEYOND } `, name: 'serviceB', }, ]; const definitionsDocument = createDefinitionsDocumentForServices( serviceList, ); const errors = validateSDL(definitionsDocument, schema, [MatchingEnums]); expect(errors).toMatchInlineSnapshot(` Array [ Object { "code": "ENUM_MISMATCH", "locations": Array [ Object { "column": 1, "line": 2, }, Object { "column": 1, "line": 2, }, ], "message": "The \`ProductCategory\` enum does not have identical values in all services. Groups of services with identical values are: [serviceA], [serviceB]", }, ] `); }); it('errors when enums in separate services dont match', () => { const serviceList = [ { typeDefs: gql` type Query { products: [Product]! } type Product @key(fields: "sku") { sku: String! upc: String! type: ProductType } enum ProductType { BOOK FURNITURE } `, name: 'serviceA', }, { typeDefs: gql` enum ProductType { FURNITURE BOOK DIGITAL } `, name: 'serviceB', }, { typeDefs: gql` enum ProductType { FURNITURE BOOK DIGITAL } `, name: 'serviceC', }, ]; const definitionsDocument = createDefinitionsDocumentForServices( serviceList, ); const errors = validateSDL(definitionsDocument, schema, [MatchingEnums]); expect(errors).toMatchInlineSnapshot(` Array [ Object { "code": "ENUM_MISMATCH", "locations": Array [ Object { "column": 1, "line": 12, }, Object { "column": 1, "line": 2, }, Object { "column": 1, "line": 2, }, ], "message": "The \`ProductType\` enum does not have identical values in all services. Groups of services with identical values are: [serviceA], [serviceB, serviceC]", }, ] `); }); it('errors when an enum name is defined as another type in a service', () => { const serviceList = [ { typeDefs: gql` enum ProductType { BOOK FURNITURE } `, name: 'serviceA', }, { typeDefs: gql` type ProductType { id: String } `, name: 'serviceB', }, { typeDefs: gql` enum ProductType { FURNITURE BOOK DIGITAL } `, name: 'serviceC', }, ]; const definitionsDocument = createDefinitionsDocumentForServices( serviceList, ); const errors = validateSDL(definitionsDocument, schema, [MatchingEnums]); expect(errors).toMatchInlineSnapshot(` Array [ Object { "code": "ENUM_MISMATCH_TYPE", "locations": Array [ Object { "column": 1, "line": 2, }, Object { "column": 1, "line": 2, }, Object { "column": 1, "line": 2, }, ], "message": "[serviceA] ProductType -> ProductType is an enum in [serviceA, serviceC], but not in [serviceB]", }, ] `); }); });