Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions __tests__/supergraph/base.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,38 @@ testVersions((api, version) => {
expect(result.supergraphSdl).not.toContain("directive @a(n: Int)");
});

test("non-composed executable directive with QUERY | MUTATION is omitted if only defined within a single subgraph", () => {
const result = api.composeServices([
{
name: "a",
url: "http://a.com",
typeDefs: graphql`
extend schema
@link(url: "https://specs.apollo.dev/federation/${version}", import: ["@key"])

directive @a(n: Int) on QUERY | MUTATION

type Query {
a: Int
}
`,
},
{
name: "b",
url: "http://b.com",
typeDefs: graphql`
extend schema
@link(url: "https://specs.apollo.dev/federation/${version}", import: ["@key"])

type Query {
b: Int
}
`,
},
]);
expect(result.supergraphSdl).not.toContain("directive @a");
});

test("executable directive only contains locations shared between all subgraphs", () => {
const result = api.composeServices([
{
Expand Down Expand Up @@ -450,5 +482,119 @@ testVersions((api, version) => {
}
`);
});

test("composed directive with only executable locations is preserved in supergraph", () => {
const result = api.composeServices([
{
name: "a",
url: "http://a.com",
typeDefs: graphql`
extend schema
@link(url: "https://specs.apollo.dev/federation/${version}", import: ["@composeDirective"])
@link(url: "https://a.dev/a/v1.0", import: ["@a"])
@composeDirective(name: "@a")

directive @a(name: String!) on QUERY | MUTATION

type Query {
a: Int
}
`,
},
{
name: "b",
url: "http://b.com",
typeDefs: graphql`
extend schema
@link(url: "https://specs.apollo.dev/federation/${version}", import: [])

type Query {
b: Int
}
`,
},
]);

assertCompositionSuccess(result);
expect(result.supergraphSdl).toContainGraphQL(graphql`
directive @a(name: String!) on QUERY | MUTATION
`);
});

test("composed directive with VARIABLE_DEFINITION and FIELD locations is preserved in supergraph", () => {
const result = api.composeServices([
{
name: "a",
url: "http://a.com",
typeDefs: graphql`
extend schema
@link(url: "https://specs.apollo.dev/federation/${version}", import: ["@composeDirective"])
@link(url: "https://a.dev/a/v1.0", import: ["@a"])
@composeDirective(name: "@a")

directive @a(provider: String!) on VARIABLE_DEFINITION | FIELD

type Query {
a: Int
}
`,
},
{
name: "b",
url: "http://b.com",
typeDefs: graphql`
extend schema
@link(url: "https://specs.apollo.dev/federation/${version}", import: [])

type Query {
b: Int
}
`,
},
]);

assertCompositionSuccess(result);
expect(result.supergraphSdl).toContainGraphQL(graphql`
directive @a(provider: String!) on VARIABLE_DEFINITION | FIELD
`);
});

test("composed directive with mixed schema and executable locations is preserved when only one subgraph defines it", () => {
const result = api.composeServices([
{
name: "a",
url: "http://a.com",
typeDefs: graphql`
extend schema
@link(url: "https://specs.apollo.dev/federation/${version}", import: ["@composeDirective"])
@link(url: "https://a.dev/a/v1.0", import: ["@a"])
@composeDirective(name: "@a")

directive @a(n: Int) on FIELD | FIELD_DEFINITION

type Query {
a: Int
}
`,
},
{
name: "b",
url: "http://b.com",
typeDefs: graphql`
extend schema
@link(url: "https://specs.apollo.dev/federation/${version}", import: [])

type Query {
b: Int
}
`,
},
]);

assertCompositionSuccess(result);
expect(result.supergraphSdl).toContainGraphQL(graphql`
directive @a(n: Int) on FIELD | FIELD_DEFINITION
`);
});
}
});
6 changes: 5 additions & 1 deletion src/supergraph/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,11 @@ export function createSupergraphStateBuilder() {

// Strip out all executable directives that are not defined or identical every supergraph
for (const directiveState of state.directives.values()) {
if (!directiveState.isExecutable || !directiveState.byGraph.size) {
if (
!directiveState.isExecutable ||
!directiveState.byGraph.size ||
directiveState.composed
) {
continue;
}

Expand Down
Loading