graphql-tools icon indicating copy to clipboard operation
graphql-tools copied to clipboard

Mocked values for fields that take in parameters are not respected when provided in a list

Open nickiepucel opened this issue 11 months ago • 1 comments

Issue workflow progress

Progress of the issue based on the Contributor Workflow

  • [ ] 1. The issue provides a reproduction available on Github, Stackblitz or CodeSandbox

    Make sure to fork this template and run yarn generate in the terminal.

    Please make sure the GraphQL Tools package versions under package.json matches yours.

  • [ ] 2. A failing test has been provided
  • [ ] 3. A local solution has been provided
  • [ ] 4. A pull request is pending review

Describe the bug

Mocked values for fields that take in parameters are not respected when provided in a list.

If you have a field on an object that takes in parameters, and you attempt to mock that field in a list of those objects, the mocked value for the field is ignored, and a default value is provided instead.

To Reproduce Steps to reproduce the behavior:

The following code can be used to reproduce the issue

import { addMocksToSchema } from "@graphql-tools/mock";
import { makeExecutableSchema } from "@graphql-tools/schema";
import { graphql } from "graphql";

const typeDefs = `#graphql
  type UserGroup {
    id: ID!
    users: [User!]!
  }

  type User {	
    id: ID!
    # User has a nullable membership field that takes in some input
    membership(param: String!): Membership
  }

  type Membership {
    id: ID!
  }

  type Query {
    getUserGroup: UserGroup
  }
`;

const query = /* GraphQL */ `
  query GetUserGroup {
    getUserGroup {
      id
      users {
        id
        # input is provided in the query here
        membership(param: "test") {
          id
        }
      }
    }
  }
`;

const mockSchema = addMocksToSchema({
  schema: makeExecutableSchema({
    typeDefs,
  }),

  mocks: {
    UserGroup: () => ({
      users: [
        // Neither of these overrides work
        { membership: null },
        { membership: { id: "mock-membership-id" } },
      ],
    }),
  },
});

graphql(mockSchema, query).then((result) => console.log("Got result", result));

The result that is printed out: As json

{
  "data": {
    "getUserGroup": {
      "id": "875ca18b-66a7-4633-a47e-1d57de90a176",
      "users": [
        {
          "id": "cbb42248-9cbd-48ab-a86c-438cd41ec6f6",
          "membership": {
            "id": "ee1a9260-4e4e-4778-8ef0-dd8754c88c6f"
          }
        },
        {
          "id": "51742853-07b0-4666-906e-2377d21433de",
          "membership": {
            "id": "6e8e08af-398a-4f1a-806b-f8b2d92a43b0"
          }
        }
      ]
    }
  }
}

Screenshot of browser console: image

Expected behavior

The overrides should work, and the returned result should be:

{
  "data": {
    "getUserGroup": {
      "id": "f1d3506d-9901-412e-aee1-0114f76a4f62",
      "users": [
        {
          "id": "ca41e01f-e45e-4f10-8eb5-f143432fdd69",
          "membership": null
        },
        {
          "id": "6cfba26e-1b7e-4a4e-9dec-99eb2fa54e1d",
          "membership": {
            "id": "mock-membership-id"
          }
        }
      ]
    }
  }
}

Environment:

  • OS: macOS 14.6.1
  • @graphql-tools/mock: 9.0.1
  • @graphql-tools/schema: 10.0.2
  • graphql: 15.8.0
  • NodeJS: v20.11.1

Additional context

The overrides work as expected with minor tweaks:

  • If you make param optional, and don't pass one in in the query, the overrides work
  • Overriding membership via mocking User works as expected
User: () => ({ membership: null }) // this works
  • The bug also presents itself when the field returns a primitive rather than an object type
type User {
  # mocks provided for name in the list would also be ignored
  name(param: String!): String
}

nickiepucel avatar Oct 30 '24 18:10 nickiepucel