Skip to content
This repository was archived by the owner on Dec 28, 2025. It is now read-only.

Repository files navigation

graphql-test

testing GraphQL corner case

ディレクトリ構造

実験1: インラインフラグメントにネストしたオブジェクトをルートオブジェクトにマージするときの動作

検証するリクエスト。

query MergeConcreteTypeInRootFieldAndInterfaceFragment {
    productA {
        package {
            id
            name
        }
        ... on AbstractProduct {
            ...ProductDetail
        }
    }
}

fragment ProductDetail on AbstractProduct {
    ... on ProductB {
        package {
            displayOwner: owner {
                name
            }
            owners { name }
        }
    }
    ... on ProductA {
        package {
            displayOwner: owner {
                name
            }
            owners { name }
        }
    }
}

期待するレスポンス。

{
  "data": {
    "productA": {
      "package": {
        "id": "1",
        "name": "pkgA",
        "displayOwner": {
          "name": "owner1"
        },
        "owners": [
          {
            "name": "owner1"
          }
        ]
      }
    }
  }
}

実験結果

  • 期待するレスポンスが得られた構成
    • backend/go-gqlgen
    • backend/node-apollo-server
    • backend/perl-graphql-perl
    • backend/ruby-graphql-perl
    • router/rust-apollo-router + backend
  • 期待するレスポンスが得られなかった構成
    • router/go-wundergraph-cosmo + backend
    • router/node-apollo-gateway + backend

期待と異なるレスポンス。インラインフラグメントにネストしたオブジェクトのフィールドが消えてしまう。

{
  "data": {
    "productA": {
      "package": {
        "id": "1",
        "name": "pkgA"
      }
    }
  }
}

実験2: インラインフラグメントにネストしたオブジェクトのリスト型のフィールドをマージするときの動作

検証するリクエスト。

query MergeInlineFragment {
    itemList {
        __typename
        ...ItemA
        ...ItemB
    }
}

fragment ItemA on ItemA {
    name
    productList {
        __typename
        package {
            id
        }
    }
}
fragment ItemB on ItemB {
    name
    productList {
        __typename
        package {
            id
        }
    }
}

期待するレスポンス。

{
  "data": {
    "itemList": [
      {
        "__typename": "ItemA",
        "name": "itemA",
        "productList": [
          {
            "__typename": "ProductA",
            "package": {
              "id": "1"
            }
          },
          {
            "__typename": "ProductA",
            "package": {
              "id": "2"
            }
          }
        ]
      },
      {
        "__typename": "ItemB",
        "name": "itemB",
        "productList": [
          {
            "__typename": "ProductB",
            "package": {
              "id": "2"
            }
          },
          {
            "__typename": "ProductB",
            "package": {
              "id": "3"
            }
          }
        ]
      }
    ]
  }
}

実験結果

  • 期待するレスポンスが得られた構成
    • backend/go-gqlgen
    • backend/node-apollo-server
    • router/rust-apollo-router + backend/go-gqlgen
    • router/rust-apollo-router + backend/node-apollo-server
    • router/node-apollo-gateway + backend/go-gqlgen
    • router/node-apollo-gateway + backend/node-apollo-server
  • 期待するレスポンスが得られなかった構成
    • backend/perl-graphql-perl
    • backend/ruby-graphql-perl
    • router/go-wundergraph-cosmo + backend/perl-graphql-perl
    • router/go-wundergraph-cosmo + backend/ruby-graphql-perl
    • router/rust-apollo-router + backend/perl-graphql-perl
    • router/rust-apollo-router + backend/ruby-graphql-perl
    • router/node-apollo-gateway + backend/perl-graphql-perl
    • router/node-apollo-gateway + backend/ruby-graphql-ruby

期待と異なるレスポンス。routerと関係なくbackend単体でもエラーになるようだ。

backend/perl-graphql-perl

{
  "errors": [
    {
      "locations": [
        {
          "line": "59",
          "column": "1"
        }
      ],
      "path": [
        "itemList",
        "0"
      ],
      "message": "Can't call method \"isa\" on an undefined value at /app/local/lib/perl5/GraphQL/Role/Abstract.pm line 59.\n"
    }
  ],
  "data": null
}

backend/ruby-graphql-perl

<h1>Internal Server Error</h1>

router/go-wundergraph-cosmo + backend/perl-graphql-perl

{
  "errors": [
    {
      "message": "Failed to fetch from Subgraph 'perl'.",
      "extensions": {
        "errors": [
          {
            "path": [
              "itemList",
              "0"
            ],
            "message": "Can't call method \"isa\" on an undefined value at /app/local/lib/perl5/GraphQL/Role/Abstract.pm line 59.\n",
            "extensions": {
              "code": "DOWNSTREAM_SERVICE_ERROR"
            }
          }
        ],
        "serviceName": "perl"
      }
    }
  ],
  "data": null
}

router/go-wundergraph-cosmo + backend/ruby-graphql-perl

{
  "errors": [
    {
      "message": "500: Internal Server Error"
    }
  ],
  "data": null
}

router/rust-apollo-router + backend/perl-graphql-perl

{
  "data": null,
  "errors": [
    {
      "message": "Subgraph errors redacted",
      "path": []
    }
  ]
}

router/rust-apollo-router + backend/ruby-graphql-perl

{
  "data": null,
  "errors": [
    {
      "message": "Subgraph errors redacted",
      "path": []
    },
    {
      "message": "Subgraph errors redacted",
      "path": []
    }
  ]
}

router/node-apollo-gateway + backend/perl-graphql-perl

{
  "errors": [
    {
      "message": "Can't call method \"isa\" on an undefined value at /app/local/lib/perl5/GraphQL/Role/Abstract.pm line 59.\n",
      "path": [
        "itemList",
        "0"
      ],
      "extensions": {
        "serviceName": "perl",
        "code": "DOWNSTREAM_SERVICE_ERROR",
        "stacktrace": [
          "GraphQLError: Can't call method \"isa\" on an undefined value at /app/local/lib/perl5/GraphQL/Role/Abstract.pm line 59.",
          "",
          "    at Object.err (/app/node_modules/.pnpm/@apollo+federation-internals@2.12.2_graphql@16.12.0/node_modules/@apollo/federation-internals/dist/error.js:11:32)",
          "    at downstreamServiceError (/app/node_modules/.pnpm/@apollo+gateway@2.12.2_encoding@0.1.13_graphql@16.12.0/node_modules/@apollo/gateway/dist/executeQueryPlan.js:523:120)",
          "    at /app/node_modules/.pnpm/@apollo+gateway@2.12.2_encoding@0.1.13_graphql@16.12.0/node_modules/@apollo/gateway/dist/executeQueryPlan.js:341:59",
          "    at Array.map (<anonymous>)",
          "    at sendOperation (/app/node_modules/.pnpm/@apollo+gateway@2.12.2_encoding@0.1.13_graphql@16.12.0/node_modules/@apollo/gateway/dist/executeQueryPlan.js:341:44)",
          "    at process.processTicksAndRejections (node:internal/process/task_queues:103:5)",
          "    at async /app/node_modules/.pnpm/@apollo+gateway@2.12.2_encoding@0.1.13_graphql@16.12.0/node_modules/@apollo/gateway/dist/executeQueryPlan.js:255:49",
          "    at async executeNode (/app/node_modules/.pnpm/@apollo+gateway@2.12.2_encoding@0.1.13_graphql@16.12.0/node_modules/@apollo/gateway/dist/executeQueryPlan.js:200:17)",
          "    at async /app/node_modules/.pnpm/@apollo+gateway@2.12.2_encoding@0.1.13_graphql@16.12.0/node_modules/@apollo/gateway/dist/executeQueryPlan.js:96:35",
          "    at async /app/node_modules/.pnpm/@apollo+gateway@2.12.2_encoding@0.1.13_graphql@16.12.0/node_modules/@apollo/gateway/dist/index.js:112:38"
        ]
      }
    }
  ],
  "data": null
}

router/node-apollo-gateway + backend/ruby-graphql-perl

{
  "errors": [
    {
      "message": "500: Internal Server Error",
      "extensions": {
        "response": {
          "url": "http://backend-ruby-graphql-ruby:8084/graphql",
          "status": 500,
          "statusText": "Internal Server Error",
          "body": "<h1>Internal Server Error</h1>"
        },
        "code": "INTERNAL_SERVER_ERROR",
        "stacktrace": [
          "GraphQLError: 500: Internal Server Error",
          "    at RemoteGraphQLDataSource.errorFromResponse (/app/node_modules/.pnpm/@apollo+gateway@2.12.2_encoding@0.1.13_graphql@16.12.0/node_modules/@apollo/gateway/dist/datasources/RemoteGraphQLDataSource.js:176:16)",
          "    at process.processTicksAndRejections (node:internal/process/task_queues:103:5)",
          "    at async RemoteGraphQLDataSource.sendRequest (/app/node_modules/.pnpm/@apollo+gateway@2.12.2_encoding@0.1.13_graphql@16.12.0/node_modules/@apollo/gateway/dist/datasources/RemoteGraphQLDataSource.js:108:23)",
          "    at async RemoteGraphQLDataSource.process (/app/node_modules/.pnpm/@apollo+gateway@2.12.2_encoding@0.1.13_graphql@16.12.0/node_modules/@apollo/gateway/dist/datasources/RemoteGraphQLDataSource.js:83:26)",
          "    at async sendOperation (/app/node_modules/.pnpm/@apollo+gateway@2.12.2_encoding@0.1.13_graphql@16.12.0/node_modules/@apollo/gateway/dist/executeQueryPlan.js:326:26)",
          "    at async /app/node_modules/.pnpm/@apollo+gateway@2.12.2_encoding@0.1.13_graphql@16.12.0/node_modules/@apollo/gateway/dist/executeQueryPlan.js:255:49",
          "    at async executeNode (/app/node_modules/.pnpm/@apollo+gateway@2.12.2_encoding@0.1.13_graphql@16.12.0/node_modules/@apollo/gateway/dist/executeQueryPlan.js:200:17)",
          "    at async /app/node_modules/.pnpm/@apollo+gateway@2.12.2_encoding@0.1.13_graphql@16.12.0/node_modules/@apollo/gateway/dist/executeQueryPlan.js:96:35",
          "    at async /app/node_modules/.pnpm/@apollo+gateway@2.12.2_encoding@0.1.13_graphql@16.12.0/node_modules/@apollo/gateway/dist/index.js:112:38",
          "    at async execute (/app/node_modules/.pnpm/@apollo+server@5.2.0_graphql@16.12.0/node_modules/@apollo/server/dist/cjs/requestPipeline.js:245:28)"
        ]
      }
    }
  ],
  "data": null
}

About

testing GraphQL corner case

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages