mercurius-js / mercurius-gateway

Mercurius federation support plugin
MIT License
17 stars 11 forks source link

Error when performing queries with variable inside array literal #95

Open mazei513 opened 1 year ago

mazei513 commented 1 year ago

When running a query with variables inside array literal, an error Variable "$varName" is not defined by operation "Query_fieldName".. For example,

# With this schema
extend type Query {
  searchUsers (ids: [ID!]!): [User]
}

# The following query fails
query search($userId: ID!) {
  searchUsers(ids: [$userId]) {
    id
  }
}

Operations like these work on Apollo Server. When I added a similar query into the base mercurius repo's tests, it also passes. Only in mercurius-gateway it fails.

The following test fails.

test('It support variable inside array literal', async t => {
  const users = [{
    id: 'u1',
    name: {
      firstName: 'John',
      lastName: 'Doe'
    }
  }, {
    id: 'u2',
    name: {
      firstName: 'Jane',
      lastName: 'Doe'
    }
  }]

  const [userService, userServicePort] = await createService(
    t,
    `
    directive @customDirective on FIELD_DEFINITION

    extend type Query {
      searchUsers (ids: [ID!]!): [User]
    }

    type User @key(fields: "id") {
      id: ID!
      name: UserName!
    }

    type UserName {
      firstName: String!
      lastName: String!
    }
  `,
    {
      Query: {
        searchUsers: (root, args) => {
          return users.filter((u) => args.ids.includes(u.id))
        }
      }
    }
  )

  const gateway = Fastify()
  t.teardown(async () => {
    await gateway.close()
    await userService.close()
  })

  await gateway.register(plugin, {
    gateway: {
      services: [
        {
          name: 'user',
          url: `http://localhost:${userServicePort}/graphql`
        }
      ]
    }
  })

  const query = `
  query MainQuery(
    $userId: ID!
  ){
    searchUsers (ids: [$userId]) {
      id
      name {
        firstName
        lastName
      }
    }
  }`

  const res = await gateway.inject({
    method: 'POST',
    headers: {
      'content-type': 'application/json'
    },
    url: '/graphql',
    body: JSON.stringify({
      query,
      variables: {
        userId: 'u1'
      }
    })
  })

  t.same(JSON.parse(res.body), {
    data: {
      searchUsers: [users[0]]
    }
  })
})
firelegacy0 commented 1 year ago

Sorry for the direct ping @mcollina, we'd appreciate any insights as to what may possibly be responsible for this issue.

We're happy to help investigate and fix this. Any direction will be helpful as we'd love to use Mercurius, but this is currently a blocker for us to adopting it fully.