console/integration-tests/tests/schema/contracts.spec.ts

351 lines
8.8 KiB
TypeScript

import { getServiceHost } from 'testkit/utils';
import type { SchemaBuilderApi } from '@hive/schema';
import { createTRPCProxyClient, httpLink } from '@trpc/client';
const host =
process.env['SCHEMA_SERVICE_HOST_OVERRIDE'] ||
(await getServiceHost('schema', 3002).then(r => `http://${r}`));
const client = createTRPCProxyClient<SchemaBuilderApi>({
links: [
httpLink({
url: host + `/trpc`,
fetch,
}),
],
});
describe('schema service can process contracts', () => {
test('single', async () => {
const result = await client.composeAndValidate.mutate({
type: 'federation',
native: true,
schemas: [
{
raw: /* GraphQL */ `
extend schema
@link(url: "https://specs.apollo.dev/link/v1.0")
@link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@tag"])
type Query {
hello: String
helloHidden: String @tag(name: "toyota")
}
`,
source: 'foo.graphql',
url: null,
},
{
raw: /* GraphQL */ `
extend schema
@link(url: "https://specs.apollo.dev/link/v1.0")
@link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@tag"])
type Query {
bar: String
barHidden: String @tag(name: "toyota")
}
`,
source: 'bar.graphql',
url: null,
},
],
external: null,
contracts: [
{
id: 'foo',
filter: {
include: null,
exclude: ['toyota'],
removeUnreachableTypesFromPublicApiSchema: false,
},
},
],
});
expect(result.contracts?.[0].sdl).toMatchInlineSnapshot(`
type Query {
bar: String
hello: String
}
`);
});
test('multiple', async () => {
const result = await client.composeAndValidate.mutate({
type: 'federation',
native: true,
schemas: [
{
raw: /* GraphQL */ `
extend schema
@link(url: "https://specs.apollo.dev/link/v1.0")
@link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@tag"])
type Query {
hello: String
helloHidden: String @tag(name: "toyota")
}
`,
source: 'foo.graphql',
url: null,
},
{
raw: /* GraphQL */ `
extend schema
@link(url: "https://specs.apollo.dev/link/v1.0")
@link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@tag"])
type Query {
bar: String
barHidden: String @tag(name: "toyota")
}
`,
source: 'bar.graphql',
url: null,
},
],
external: null,
contracts: [
{
id: 'foo',
filter: {
include: null,
exclude: ['toyota'],
removeUnreachableTypesFromPublicApiSchema: false,
},
},
{
id: 'bar',
filter: {
include: ['toyota'],
exclude: null,
removeUnreachableTypesFromPublicApiSchema: false,
},
},
],
});
expect(result.contracts?.[0].sdl).toMatchInlineSnapshot(`
type Query {
bar: String
hello: String
}
`);
expect(result.contracts?.[1].sdl).toMatchInlineSnapshot(`
type Query {
barHidden: String
helloHidden: String
}
`);
});
test('remove unreachable types from public schema', async () => {
const result = await client.composeAndValidate.mutate({
type: 'federation',
native: true,
schemas: [
{
raw: /* GraphQL */ `
extend schema
@link(url: "https://specs.apollo.dev/link/v1.0")
@link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@tag"])
type Query {
hello: String
helloHidden: Toyota @tag(name: "toyota")
}
type Toyota {
id: String!
}
`,
source: 'foo.graphql',
url: null,
},
],
external: null,
contracts: [
{
id: 'foo',
filter: {
include: null,
exclude: ['toyota'],
removeUnreachableTypesFromPublicApiSchema: true,
},
},
],
});
expect(result.contracts?.[0].sdl).toMatchInlineSnapshot(`
type Query {
hello: String
}
`);
});
test('keep unreachable types from public schema', async () => {
const result = await client.composeAndValidate.mutate({
type: 'federation',
native: true,
schemas: [
{
raw: /* GraphQL */ `
extend schema
@link(url: "https://specs.apollo.dev/link/v1.0")
@link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@tag"])
type Query {
hello: String
helloHidden: Toyota @tag(name: "toyota")
}
type Toyota {
id: String!
}
`,
source: 'foo.graphql',
url: null,
},
],
external: null,
contracts: [
{
id: 'foo',
filter: {
include: null,
exclude: ['toyota'],
removeUnreachableTypesFromPublicApiSchema: false,
},
},
],
});
expect(result.contracts?.[0].sdl).toMatchInlineSnapshot(`
type Query {
hello: String
}
type Toyota {
id: String!
}
`);
// there should be no @inaccessible on federation specific types otherwise apollo router goes brrrt
expect(result.contracts?.[0].supergraph).toContain('enum join__Graph {');
expect(result.contracts?.[0].supergraph).toContain('scalar link__Import\n');
expect(result.contracts?.[0].supergraph).toContain('scalar join__FieldSet\n');
});
});
test('federation schema contains list of tags', async () => {
const result = await client.composeAndValidate.mutate({
type: 'federation',
native: true,
schemas: [
{
raw: /* GraphQL */ `
extend schema
@link(url: "https://specs.apollo.dev/link/v1.0")
@link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@tag"])
type Query {
hello: String
helloHidden: String @tag(name: "toyota") @tag(name: "turtle")
}
`,
source: 'foo.graphql',
url: null,
},
],
external: null,
contracts: [
{
id: 'foo',
filter: {
include: null,
exclude: ['toyota'],
removeUnreachableTypesFromPublicApiSchema: false,
},
},
],
});
expect(result.tags).toMatchInlineSnapshot(`
[
toyota,
turtle,
]
`);
});
test('nothing is removed from schema as everything is included yields no errors', async () => {
await client.composeAndValidate.mutate({
type: 'federation',
native: true,
schemas: [
{
raw: /* GraphQL */ `
extend schema
@link(url: "https://specs.apollo.dev/link/v1.0")
@link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@tag"])
type Query {
hello: String @tag(name: "toyota")
helloHidden: String @tag(name: "toyota")
foo: String @tag(name: "toyota")
}
`,
source: 'foo.graphql',
url: null,
},
],
external: null,
contracts: [
{
id: 'foo',
filter: {
include: ['toyota'],
exclude: null,
removeUnreachableTypesFromPublicApiSchema: true,
},
},
],
});
});
test('failed contract composition has errors and no sdl and supergraph', async () => {
const result = await client.composeAndValidate.mutate({
type: 'federation',
native: true,
schemas: [
{
raw: /* GraphQL */ `
extend schema
@link(url: "https://specs.apollo.dev/link/v1.0")
@link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@tag"])
type Query {
hello: String @tag(name: "toyota")
helloHidden: String @tag(name: "toyota")
bar: String @tag(name: "toyota")
}
`,
source: 'foo.graphql',
url: null,
},
],
external: null,
contracts: [
{
id: 'foo',
filter: {
removeUnreachableTypesFromPublicApiSchema: true,
exclude: ['toyota'],
include: null,
},
},
],
});
expect(result.contracts?.[0].sdl).toEqual(null);
expect(result.contracts?.[0].supergraph).toEqual(null);
expect(result.contracts?.[0].errors).toBeDefined();
});