Skip to content
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

graphql.link() doesn't intercept request #342

Closed
hugotiburtino opened this issue Aug 18, 2020 · 9 comments
Closed

graphql.link() doesn't intercept request #342

hugotiburtino opened this issue Aug 18, 2020 · 9 comments
Labels
api:graphql bug Something isn't working scope:node Related to MSW running in Node

Comments

@hugotiburtino
Copy link

hugotiburtino commented Aug 18, 2020

Environment

Name Version
msw 0.20.5
node 12.18.3
OS Ubuntu 20.04

Request handlers

  const serloApi = graphql.link('https://api.serlo.org/graphql')
  global.server.use(
    serloApi.query('_cacheKeys', async(req, res, ctx) =>{
      return res(
        ctx.data(
          await server.executeOperation({
            query: worker.queryLiteral,
          } as GraphQLRequest)
        )
      )
    })
  )
})

Actual request

import { GraphQLClient, gql } from 'graphql-request'
...
 private query = gql`{ _cacheKeys (first: 5, after: ...
await this.grahQLClient.request(this.query).then(async (data) =>  console.log('data: ', data))
...

Current behavior

The request by-passes the interceptor and goes to the actual server, which responds with 400 (since the feature doesn't exit yet).

Cannot query field "_cacheKeys" on type "Query".: {"response":{"errors":[{"message":"Cannot query field \"_cacheKeys\" on type \"Query\".","locations":[{"line":2,"column":7}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"status":400},"request":{"query":"\n    { _cacheKeys (first: 5, after: \"\") { edges { cursor node } nodes totalCount  pageInfo { hasNextPage hasPreviousPage startCursor endCursor } } }\n  "}}

Expected behavior

To get the same response that I have when I mock the GraphQL server using the rest object

    data:  {
      _cacheKeys: {
        edges: [ [Object], [Object], [Object], [Object], [Object] ],
        nodes: [ 'key0', 'key1', 'key2', 'key3', 'key4' ],
        totalCount: 25,
        pageInfo: {
          hasNextPage: true,
          hasPreviousPage: false,
          startCursor: 'a2V5MA==',
          endCursor: 'a2V5NA=='
        }
      }
    }

To Reproduce

  1. git clone https://github.com/hugotiburtino/api.serlo.org.git (commit 80b09a)
  2. yarn install
  3. yarn test __tests__/worker.ts
@hugotiburtino hugotiburtino added bug Something isn't working scope:node Related to MSW running in Node labels Aug 18, 2020
@marcosvega91
Copy link
Member

Hi @hugotiburtino thanks for opening the issue :).

I have looked at your code and I think that your implementation is right. The problem I think is how graphql requests are handled in the parseQuery function

msw/src/graphql.ts

Lines 76 to 91 in 2478051

export function parseQuery(
query: string,
definitionOperation: OperationTypeNode = 'query',
): ParsedQueryPayload {
const ast = parse(query)
const operationDef = ast.definitions.find(
(def) =>
def.kind === 'OperationDefinition' &&
def.operation === definitionOperation,
) as OperationDefinitionNode
return {
operationName: operationDef?.name?.value,
}
}
.

The operation name from parse function is null for your case because _cacheKeys is a field name.

This makes me worry about another thing, in a single graphql request multiple query can be send but I think that this not handled.

@kettanaito
Copy link
Member

A GraphQL request must be named in order to be matched with MSW. In your example you have an untitled request.

-{ _cacheKeys: {} }
+query GetCacheKeys { _cacheKeys: {} }

You use the name of the query when creating a request handler:

import { graphql } from 'msw'

graphql.query('GetCacheKeys', resolver)

We are currently elaborating on supporting an operation-based interception (#184), so stay tuned for updates.

@kettanaito
Copy link
Member

@marcosvega91, I think you are right. Would you be interested in adding a new integration test to MSW to illustrate that we fail to handle a scenario when a single request contains multiple named GraphQL queries?

@hugotiburtino
Copy link
Author

Thanks, that solved my issue

@marcosvega91
Copy link
Member

@marcosvega91, I think you are right. Would you be interested in adding a new integration test to MSW to illustrate that we fail to handle a scenario when a single request contains multiple named GraphQL queries?

Yes I'll create a test case :)

@marcosvega91
Copy link
Member

marcosvega91 commented Aug 20, 2020

I have looked better to the spec and there is no official support for multi query in a single operation so I think that we are good for now 😄

@kettanaito
Copy link
Member

kettanaito commented Aug 20, 2020

I think there was a confusion over query name and fields. Each query has a single name, but may request multiple fields.

# `GetUser` is the name
query GetUser($userId: String!) {
  # `user` is a field
  user: {
    firstName
    lastName
  }
  # `subscriptions` is a field
  subscriptions: {
    filterBy(userId: $userId) {
      validUntil
    }
  }
}

@marcosvega91
Copy link
Member

Yes I thought that a single fetch with multiple operations could be possibile. Do we want to add a test case with your example?

@kettanaito
Copy link
Member

I think there is no need. That test is going to assert that given JSON produces the respective response body. We already have such test.

@github-actions github-actions bot locked and limited conversation to collaborators Nov 16, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api:graphql bug Something isn't working scope:node Related to MSW running in Node
Projects
None yet
Development

No branches or pull requests

3 participants