npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

graphql-fixtures

v8.0.1

Published

Utilities for generating fixture objects from GraphQL documents.

Downloads

391,766

Readme

graphql-fixtures

Build Status Build Status License: MIT npm version

Utilities for generating fixture objects from GraphQL documents.

Installation

yarn add graphql-fixtures

Usage

createFillers(schema: GraphQLSchema, options?: Options): {fillOperation: Filler, fillFragment: Filler}

Returns functions that will be used to create object fixtures. This function takes the GraphQL schema (which will be used to generate the correct type of data given the document), and an optional object with the following properties:

  • resolvers: an object whose keys are names of types in the passed schema, and whose values are functions that return a fixture version of that type. This function can return a partial fixture; the default resolvers will then fill the remainder of the object. The function will be called two arguments: the GraphQL request (including variables), and details about the type and field currently being filled. You could use this to, for example, create dynamic values for a type based on the object in which it resides:

    let currentID = 1;
    const {fillOperation} = createFillers(schema, {
      resolvers: {
        ID: (_, {parent}) => `gid://${parent.name}/${currentID++}`,
      },
    });

    If you return a fixture for an object type, the value of the fields you provide will be preferred over resolvers for the types of those fields.

    This library provides default fillers for all scalar types (including custom scalars, which will be filled as a random string value). It also will automatically select a random value from any enum type by default.

The functions returned from createFillers has the following signature:

function fillOperation<Data, Variables, PartialData>(
  // GraphQLOperation comes from graphql-typed, and is satisfied by
  // an import from a .graphql file and an asynchronous query component
  // from `@shopify/react-graphql`
  operation: GraphQLOperation<Data, Variables, PartialData>,
  data?: GraphQLFillerData<GraphQLOperation<Data, Variables, PartialData>>,
): (request: GraphQLRequest) => Data;

function fillFragment<Data, Variables, PartialData>(
  // DocumentNode comes from graphql-typed, and is satisfied by
  // an import from a .graphql file
  fragment: DocumentNode<Data, Variables, PartialData>,
  data?: GraphQLFillerData<GraphQLOperation<Data, Variables, PartialData>>,
): (request: GraphQLRequest) => Data;

A document is generated by using the gql tagged template literal or by importing a .graphql file using graphql-tag. To get automatic typing of the data that is expected for a document, use .graphql files and graphql-typescript-definitions.

The second argument is an optional data object. This object is how you can fill some set of fields each time you generate a fixture. You will usually want to use this in order to generate a fixture that has some subset of the query in a particular state, while the rest is randomly generated. The data provided here must match the shape of the data the GraphQL operation will provide, but every field and subfield is optional, and every field can either be a literal value or a function that returns a literal value. If using a function, the function will be called with the current GraphQL request (including the variables) and details about the type being filled as noted in the resolvers section above.

The return result from fillOperation or fillFragment is itself a function. When those functions are invoked respectively with a GraphQLRequest or a GraphQLFragment, they will construct the actual return value. While it may seem counter-intuitive that the function does not return an object, returning a function instead has several benefits. It means that you can pass in an asynchronous GraphQL component from @shopify/react-graphql as the first argument to fillOperation, which provides the types for the data but does not actually provide the raw query object until later. It also means that any intermediate processing that is done by your GraphQL pipeline (such as adding a __typename property) are done before any attempt to fill the operation is complete.

If you need to have the filled object immediately, you can invoke fillOperation as follows:

const data = fillOperation(myQuery, data)({query: myQuery});

Using faker

When using faker to provide fake data within your filler function, you should use the faker instance that is exported by this library in order to avoid data mismatches. Rather than import {faker} from '@faker-js/faker' instead use:

import {createFillers, faker} from 'graphql-fixtures';

const {fillOperation, fillFragment} = createFillers(schema, {
  resolvers: {
    ID: (_, {parent}) => `gid://${parent.name}/${faker.datatype.number()}`,
  },
});

Interfaces and Unions

When attempting to fill data for a union or interface type, the filler will default to selecting a random type that implements the interface/ is a member of the union. If you would like to ensure a particular type is selected, but leave all the other fields to be filled by resolvers, you can provide a __typename field in the data argument for that field that selects the type you wish to be filled.

Example

Assuming the following schema:

type Species {
  age: Number!
}

type Animal implements Species {
  name: String!
}

type Human implements Species {
  firstName: String!
  lastName: String!
}

type Query {
  species: Species
}

With the following query:

fragment HumanFragment on Human {
  firstName
  lastName
}

fragment AnimalFragment on Animal {
  name
}

query MyQuery {
  species {
    name
    ... on Human {
      ...HumanFragment
    }
    ... on Animal {
      ...AnimalFragment
    }
  }
}

We can create a simpler filler globally, and use it every time we wish to generate a fixture:

import {createFiller, faker} from 'graphql-fixtures';
import schema from './schema';
import myQuery, {HumanFragment, AnimalFragment} from './MyQuery.graphql';

const {fillOperation, fillFragment} = createFillers(schema);

// will result in {species: {__typename: '<Animal | Human>', age: <Number>, name: <String>}}
const fillMyQueryOne = fillOperation(myQuery);
s;
// will result in {__typename: 'Human', firstName: <String>, lastName: <String>}
const fillMyHumanFragment = fillFragment(HumanFragment);

// will result in {__typename: 'Animal', name: <String>}
const fillMyAnimalFragment = fillFragment(AnimalFragment);

// will result in {species: {__typename: 'Human', age: 20, firstName: '<String>>', lastName: '<String>>'}}
const fillMyQueryTwo = fillOperation(myQuery, {species: {age: 20}});

// will result in {species: {__typename: 'Animal', age: <Number>, name: 'Buddy'}}
const fillMyQueryThree = fillOperation(myQuery, {
  species: () => ({name: 'Buddy'}),
});

As noted above, individual fields can be a function that takes the current GraphQL request and details about the field, and returns the partial data. You can even do this for the entire partial object, allowing you to completely switch out what partial data is used for an invocation based on things like the variables to the current query:

import {createFiller} from 'graphql-fixtures';
import schema from './schema';
import myQuery from './MyQuery.graphql';

const {fillOperation} = createFillers(schema);

// Everything this library does is type-safe based on the original query.
// If there are required variables to the query, they will appear as required
// properties on the variables object for the request. No useless null checking!
const fillMyQuery = fillOperation(myQuery, ({variables: {first}}) => {
  return {products: list(first)};
});

list<T>(size: number | [number, number], fill?: T): T[]

Generates a list of the specified size for use in creating partially-filled data to a fill function as described above. The optional second argument is the value that will be used in each entry of the array, and so can be either a literal type the matches the list type you are filling, or a function that returns such a literal.

When a single number is provided as the first argument, an array of that size will be created. When an array with two numbers is provided, an array randomly sized in that range (inclusively) will be created.

// assuming `widgets` in a list of Widget objects
import {createFillers, faker} from 'graphql-fixtures';
import schema from './schema';
import widgetQuery from './WidgetQuery.graphql';

const {fillOperation} = createFillers(schema);

const fixture = fillOperation(widgetQuery, {
  widgets: list([2, 4], {id: () => faker.string.uuid()}),
});