graphql-codegen-typescript-mock-data icon indicating copy to clipboard operation
graphql-codegen-typescript-mock-data copied to clipboard

easily create deeply nested mock data by passing `overrides` to child generators

Open veswill3 opened this issue 2 years ago • 0 comments

I love the idea behind this plugin - it makes creating mock data for unit tests so much easier!

I was having some trouble getting the generator functions to create deeply complex mocks and wanted to ask if this was a feature that could be added. I would love to get involved and help with implementation if it is a good idea, but I wanted to open some dialog before trying to open a PR to make sure there are not good reasons for NOT doing these (technical or otherwise).

building from your example in the README, imagine if the User schema also had friends: [USER] (so we can show with a list)

If we want to create a complex User with deep fields present, we need to import several of the generator functions and call them when setting up overrides like this:

const user = aUser({
  login: 'mock-login',
  avatar: anAvatar({ url: 'https://www.some-image.jpg' }), // need to call anAvatar
  friends: [
    aUser({ id: 'friend-1' }), // we need to call aUser each of the three times
    aUser({ id: 'friend-2', status: Status.Offline }),
    aUser({ id: 'friend-3' }),
  ]
})

Instead, we could have the code generation functions forward overrides to the child generators something like this - totally untested, just showing the idea

export const aUser = (overrides?: Partial<User> | null): User | null => {
  // we need to check for null here, see comments below
  if (overrides === null) return null;
  return {
    id: overrides && overrides.hasOwnProperty('id') ? overrides.id! : 'a5756f00-41a6-422a-8a7d-d13ee6a63750',
    login: overrides && overrides.hasOwnProperty('login') ? overrides.login! : 'libero',
    // overrides are passed deep.
    // * undefined --> generate like normal
    // * null --> null (see comment above)
    avatar: anAvatar(overrides?.avatar),
    // maps over overrides to generate a list of items
    // * undefined --> generate one item as normal (or many if listElementCount is set)
    // * null --> null
    friends: overrides?.friends === null ? null : overrides?.friends?.map(aUser) ?? [aUser()],
    status: overrides && overrides.hasOwnProperty('status') ? overrides.status! : Status.Online,
    updatedAt: overrides && overrides.hasOwnProperty('updatedAt') ? overrides.updatedAt! : 1458071232,
  };
};

Now generating a complex user with everything set deep looks like this

const user2 = aUser({
  login: 'mock-login',
  avatar: { url: 'https://www.some-image.jpg' },
  friends: [
    { id: 'friend-1' },
    { id: 'friend-2', status: Status.Offline },
    { id: 'friend-3' },
  ],
});

Thoughts? Again, happy to help with implementation if this is a good idea. Let me know.

veswill3 avatar Oct 19 '22 23:10 veswill3