How to pass query arguments in graphql-tool?
Asked Answered
H

1

6

I am using graphql-tool to mock up data for testing.

I hope to simulate when I select a user, it opens a detail page and shows the user company info.

Query

const query = `
  query User($id: ID!) {
    user(id: $id) {
      id
      company
    }
  }
`;

Mock server

import { addMockFunctionsToSchema } from 'graphql-tools';
import casual from 'casual';

const allUserIds = ['u1', 'u2', 'u3'];

const mocks = {
  User: () => ({
    id: casual.random_element(allUserIds),
    name: casual.name,
    company: casual.company_name
  })
};

addMockFunctionsToSchema({ schema, mocks });

However, right now, when I query with argument id 'u1', it will return a random user id for example 'u2', which gives me a little trouble to show it in front end.

I thought I can do something like this below, but turns out I am wrong. user is undefined in the code below.

const mocks = {
  User: (user) => ({
    id: user.id || casual.random_element(allUserIds),
    name: casual.name,
    company: casual.company_name
  })
};

Is there a way to pass the query arguments in graphql-tools? Thanks

Haematothermal answered 29/1, 2019 at 0:26 Comment(2)
You're probably better off using a collection of fake/mock objects or a mock data generator with a consistent seed if you'd like to see your test data persistent throughout testing.Sewoll
@ClaireLin thanks, I did try actually. But haven't figured out where I should use casual.seed(123);. First, I tried to put on top just after import, it does not have any effect. Then I tried to put in mocks like const mocks = { User: () => { casual.seed(0); return { id: casual.random_element(allUserIds), ... } } };, it will give me all users with same info.Haematothermal
S
3

It depends on how consistent you want the test data to be. If all you care about is that the id remains consistent with your query argument, here is what you can do:

const mocks = {
  Query: () => ({
    user: (root, user) => ({
      id: user.id || casual.random_element(allUserIds),
      name: casual.name,
      company: casual.company_name
    })
  })
};

As mentioned here in the documentation, mock functions are just like GraphQL resolvers. So the parameters of the functions follow the same order of root, arguments, context that are available for each field.

Please see the code sandbox here for a live demo.

This guarantees whenever you query user with id u1, you always receive a user data object with its id = "u1" with randomly generated company and name fields. However, if you want the entire user object to be persistent throughout a test, you'll need to create the mock user data outside mock functions and query and filter out data accordingly.

Sewoll answered 29/1, 2019 at 3:28 Comment(4)
Thanks!! I missed that part document. I corrected a little bit since based on your old one User: () => ({ id: (root, { id }) => id, .... When I try to use id: (root, something) => id, something will always be empty object, which makes id is undefined. When I moved it top like User: (root, user) => ({ id: user.id || casual.random_element(allUserIds), then it works.Haematothermal
Ah you are right. I got confused with your query User and the type User with PascalCase. I'd suggest to follow the naming convention and rename the query to be camelCase user to reduce confusion.Sewoll
@HongboMiao I added a live demo and updated the code snippet here to clarify that user is in fact a query.Sewoll
Oh I did follow name conversion. I think you misunderstood my code in question. My User is under root mocks (same level with Query) which should be capitalized. It is for all User type used in all places GraphQL schema, not just in query. But anyway thanks for the direction!Haematothermal

© 2022 - 2024 — McMap. All rights reserved.