Skip to content

GraphQLInteraction doesn't match when query has no variables. #243

@ngbrown

Description

@ngbrown

I was already using PactJS to match GraphQL queries and provide responses, but the disadvantage was that they were space sensitive. I started moving some tests to use GraphQLInteraction but came across the following issue:

When the query does not supply any variables, and I don't call .withVariable(), the expected interaction still has a variables in the body. I the expected behavior would be that if the .withVariable() function isn't called (or passes null), there is no variable object in the body.

This is with @pact-foundation/pact 7.0.2.

    const interaction1 = new GraphQLInteraction()
      .given('I have an entry created for X')
      .uponReceiving('a request for recentEntriesCreated')
      .withRequest({
        method: 'POST',
        path: '/graphql',
      })
      .withOperation(recentEntriesCreatedQuery.operationName)
      .withQuery(recentEntriesCreatedQuery.query)
      .willRespondWith({
        status: 200,
        headers: {
          'Content-Type': 'application/json',
        },
        body: recentEntriesCreatedResponse,
      });

This is in the relevant parts of the log:

I, [2018-10-29T09:04:05.239946 #17820]  INFO -- : Registered expected interaction POST /graphql
D, [2018-10-29T09:04:05.240966 #17820] DEBUG -- : {
  "description": "a request for recentEntriesCreated",
  "providerState": "I have a entry created for X",
  "request": {
    "method": "POST",
    "path": "/graphql",
    "headers": {
      "content-type": "application/json"
    },
    "body": {
      "operationName": "getRecentEntriesCreatedQuery",
      "query": {
        "json_class": "Pact::Term",
        "data": {
          "generate": "query getRecentEntriesCreatedQuery {...}\\s*"}
        }
      },
      "variables": {
      }
    }
  },
  "response": {
    "status": 200,
    "headers": {
      "Content-Type": "application/json"
    },
    "body": {
      ...
    }
  }
}

The test has the following log entries:

I, [2018-10-29T09:04:05.274279 #17820]  INFO -- : Received request POST /graphql
D, [2018-10-29T09:04:05.274279 #17820] DEBUG -- : {
  "path": "/graphql",
  "query": "",
  "method": "post",
  "body": {
    "query": "query getRecentEntriesCreatedQuery {...}\n",
    "operationName": "getRecentEntriesCreatedQuery"
  },
  "headers": {
    "Content-Length": "977",
    "Content-Type": "application/json",
    "Accept": "*/*",
    "User-Agent": "node-fetch/1.0 (+https://github.com/bitinn/node-fetch)",
    "Accept-Encoding": "gzip,deflate",
    "Connection": "close",
    "Host": "localhost:4002",
    "Version": "HTTP/1.1"
  }
}
E, [2018-10-29T09:04:05.275279 #17820] ERROR -- : No matching interaction found for POST /graphql
E, [2018-10-29T09:04:05.276284 #17820] ERROR -- : Interaction diffs for that route:
E, [2018-10-29T09:04:05.278282 #17820] ERROR -- : Diff with interaction: "a request for recentEntriesCreated" given "I have a entry created for X"
Diff
--------------------------------------
Key: - is expected 
     + is actual 
Matching keys and values are not shown

 {
   "body": {
-    "variables": {
-    }
   }
 }

Description of differences
--------------------------------------
* Could not find key "variables" (keys present are: query, operationName) at $.body

If I patch node_modules/@pact-foundation/pact/dsl/graphql.js, line 96 (the last line of the json() function) with this:

if (this.state.request.body.variables == null || Object.keys(this.state.request.body.variables).length === 0) delete this.state.request.body.variables;
return this.state;

It behaves as expected. Maybe there's a better way to do it, but delete was the easiest patch I could think of.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions