-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
misbehaving spreading fragments #166
Comments
@fjmoreno are you planning to look into a fix yourself? Or would it be feasible for you to provide a failing test case? |
After debugging the issue, we found that the issue is actually due to the fragment name. When the same fragment is applied on different levels and one has directive, the directive some how gets applied to both. To be precise the To prove this, change the name of the fragment and we get the expected result. .i.e., For the same schema, change the query to
Then Result is :
So the issue is |
Please find the tests based on @fjmoreno 's example and a minimal reproduction of the bug described. import { GraphQLSchema, parse } from "graphql";
import { compileQuery, isCompiledQuery } from "../index";
import { makeExecutableSchema } from "@graphql-tools/schema";
const data = {};
function executeTestQuery(
query: string,
variables = {},
schema: GraphQLSchema
) {
const ast = parse(query);
const compiled: any = compileQuery(schema, ast, "", { debug: true } as any);
if (!isCompiledQuery(compiled)) {
return compiled;
}
return compiled.query(data, undefined, variables);
}
describe("actual example from user", () => {
const testSchema = makeExecutableSchema({
typeDefs: `type Query {
detailContent: [Content!]
}
type Post implements Content {
id: ID!
title: String!
type: String!
related: [Content]
}
type Article implements Content {
id: ID!
title: String!
type: String!
}
interface Content {
id: ID!
title: String!
type: String!
}`,
resolvers: {
Query: {
detailContent: () => [
{
__typename: "Post",
id: "post:1",
title: "Introduction to GraphQL!",
related: [
{
__typename: "Article",
id: "article:1",
title: "article Introduction to GraphQL!",
type: "article"
}
]
},
{
__typename: "Post",
id: "post:2",
title: "GraphQL-Jit a fast engine for GraphQL",
related: [
{
__typename: "Article",
id: "article:2",
title: "article GraphQL-Jit a fast engine for GraphQL",
type: "article"
}
]
},
{
__typename: "Article",
id: "article:1",
title: "article Introduction to GraphQL!",
type: "article"
},
{
__typename: "Article",
id: "article:2",
title: "article GraphQL-Jit a fast engine for GraphQL",
type: "article"
}
]
}
}
});
test("spreads misbehaving", async () => {
const query = `query TEST(
$includeOnly: Boolean!
){
detailContent{
...articleFragment
...on Post {
...postFragment
related{
id
...articleFragment1 @include(if:$includeOnly)
}
}
}
}
fragment postFragment on Post {
id
title
}
fragment articleFragment on Article {
title
type
}
fragment articleFragment1 on Article {
title
type
}`;
const result = executeTestQuery(query, { includeOnly: false }, testSchema);
console.log(JSON.stringify(result.data, null, 2));
});
test("inline behaving correctly", async () => {
const query = `query TEST(
$includeOnly: Boolean!
){
detailContent{
...on Article {
title
type
}
...on Post {
...postFragment
related{
id
...articleFragment @include(if:$includeOnly)
}
}
}
}
fragment postFragment on Post {
id
title
}
fragment articleFragment on Article {
title
type
}`;
const result = executeTestQuery(query, { includeOnly: false }, testSchema);
console.log(JSON.stringify(result.data, null, 2));
});
});
describe("reproduce minimally", () => {
const schema = makeExecutableSchema({
typeDefs: `type Query {
someQuery: [X!]
}
interface X {
id: ID!
title: String!
}
type A implements X {
id: ID!
title: String!
related: [X]
}
type B implements X {
id: ID!
title: String!
}
`,
resolvers: {
Query: {
someQuery: () => [
{
__typename: "A",
id: "a:1",
title: "a - one",
related: [
{
__typename: "B",
id: "b:1",
title: "b - one"
}
]
},
{
__typename: "B",
id: "b:1",
title: "b - one"
}
]
}
}
});
// test passes
test("testing success with include directive", async () => {
const query = `query TEST($includeOnly: Boolean!) {
someQuery {
...bFrag
...on A {
id
related {
id
...bFrag1 @include(if: $includeOnly)
}
}
}
}
fragment bFrag on B {
title
}
fragment bFrag1 on B {
title
}`;
const result = executeTestQuery(query, { includeOnly: false }, schema);
console.log(JSON.stringify(result.data, null, 2));
expect(result.data).toEqual({
someQuery: [
{
id: "a:1",
related: [
{
id: "b:1"
}
]
},
{
title: "b - one"
}
]
});
});
// test fails
test("testing the actual issue with include directive", async () => {
const query = `query TEST($includeOnly: Boolean!) {
someQuery {
...bFrag
...on A {
id
related {
id
...bFrag @include(if: $includeOnly)
}
}
}
}
fragment bFrag on B {
title
}`;
const result = executeTestQuery(query, { includeOnly: false }, schema);
console.log(JSON.stringify(result.data, null, 2));
expect(result.data).toEqual({
someQuery: [
{
id: "a:1",
related: [
{
id: "b:1"
}
]
},
{
title: "b - one"
}
]
});
});
// test passes
test("testing success with skip directive", async () => {
const query = `query TEST($skipOnly: Boolean!) {
someQuery {
...bFrag
...on A {
id
related {
id
...bFrag1 @skip(if: $skipOnly)
}
}
}
}
fragment bFrag on B {
title
}
fragment bFrag1 on B {
title
}`;
const result = executeTestQuery(query, { skipOnly: true }, schema);
console.log(JSON.stringify(result.data, null, 2));
expect(result.data).toEqual({
someQuery: [
{
id: "a:1",
related: [
{
id: "b:1"
}
]
},
{
title: "b - one"
}
]
});
});
// test fails
test("testing the actual issue with skip directive", async () => {
const query = `query TEST($includeOnly: Boolean!) {
someQuery {
...bFrag
...on A {
id
related {
id
...bFrag @skip(if: $skipOnly)
}
}
}
}
fragment bFrag on B {
title
}`;
const result = executeTestQuery(query, { skipOnly: true }, schema);
console.log(JSON.stringify(result.data, null, 2));
expect(result.data).toEqual({
someQuery: [
{
id: "a:1",
related: [
{
id: "b:1"
}
]
},
{
title: "b - one"
}
]
});
});
}); |
Given Schema:
and query:
Expect:
But receive:
The text was updated successfully, but these errors were encountered: