@cruglobal/graphql-ergonomock

中文文档
1.2.2发布于 2024/11/16MITCommonJS近 30 天下载 1万

Automatic mocking of GraphQL operations.

原始使用文档
文档目录17 节
  1. GraphQL Ergonomock
  2. Table of Contents
  3. About The Project
  4. Basic Example
  5. Basic Example (Apollo)
  6. Built With
  7. Getting Started
  8. Installation
  9. Usage
  10. API
  11. ergonomock()
  12. <ErgonoMockedProvider>
  13. Roadmap
  14. Contributing
  15. License
  16. Contact
  17. Acknowledgements

CircleCI CodeCov Contributors Forks Stargazers Issues Version MIT License


GraphQL Ergonomock

🔮 Developer-friendly automagical mocking for GraphQL
Report Bug · Request Feature

Table of Contents

About The Project

This library provides a developer-friendly method to mock your GraphQL requests. By default, it ships with the following features:

  • Automatic mocking of types and fields based on schema definition.
  • Deterministic randomization of mocked values based on the provided mock shape, to support usage of features such as snapshots.
  • Support for queries using fragments, unions & interfaces.
  • Allows usage of functions as mock values, which have the signature of a GraphQL resolver, and are resolved at runtime.

Basic Example

import { ergonomock } from 'graphql-ergonomock';

// Given a particular GraphQL Schema, ...
const schema = gql`
  type Shape {
    id: ID!
    returnInt: Int
    nestedShape: Shape
    returnBoolean: Boolean
  }

  type Query {
    getShape: Shape
  }
`;

// ...a GraphQL query, ...
const query = gql`
{
  getShape {
    id
    nestedShape {
      returnInt
      nestedShape {
        returnInt
        returnBoolean
      }
    }
  }
}
`;

// ...and a partial, possibly nested shape of data...
const mocks = {
  getShape: {
    nestedShape: {
      returnInt: 5,
      nestedShape: {
        returnInt: 10
      }
    }
  }
};

// ... provides the expected object filled with mock data
const resp = ergonomock(schema, query, { mocks });
expect(resp.data).toMatchObject({
  id: expect.toBeString(),
  nestedShape: {
    returnInt: 5,
    nestedShape: {
      returnInt: 10,
      returnBoolean: expect.toBeBoolean()
    }
  }
}); // ✅ test pass

Basic Example (Apollo)

import { ErgonoMockedProvider as MockedProvider } from "graphql-ergonomock";

// Given a particular GraphQL Schema, ...
const schema = gql`
  type Shape {
    id: ID!
    returnString: String
    returnBoolean: Boolean
  }

  type Query {
    getShape: Shape
  }
`;

// ...a component making a query ...
const QUERY = gql`
query MyQuery {
  getShape {
    id
    returnString
    returnBoolean
  }
}
`;
const MyComponent = () => {
  const { loading, error, data } = useQuery(QUERY);
  if (loading) return <p>Loading</p>;
  if (error) return <p>Error</p>;

  return (
    <div>
      MyComponent.
      <div>String: {data.getShape.returnString}</div>
      <div>Boolean: {data.getShape.returnBoolean.toString()}</div>
    </div>
  );
};

test("MyComponent can render the query results.", async () => {
  const mocks = {
    MyQuery: {
      getShape: { returnString: "John Doe" }
    }
  };
  const { findByText } = render(
    <MockedProvider schema={schema} mocks={mocks}>
      <MyComponent />
    </MockedProvider>
  );
  expect(await findByText(/String: John Doe/)).toBeVisible();
  expect(await findByText(/Boolean: (true|false)/)).toBeVisible();
}); // ✅ test pass

Built With

Getting Started

Installation

npm i graphql-ergonomock --save-dev

Usage

Default Case

The ergonomock() function can be used on its own to create mock responses out of GraphQL queries.

See example

import { ergonomock } from 'graphql-ergonomock';
import schema from '../my-schema.graphql';

test("I can mock a response", () => {
  const resp = ergonomock(schema, 'query MyCrucialOperation { car { id, plateNumber } }', {
    mocks: { car: { plateNumber: '123abc' } }
  });

  expect(resp).toMatchObject({
    data: {
      car: {
        id: expect.toBeString(),
        plateNumber: '123abc'
      }
    }
  });
});

ErgonoMockedProvider for Use with Apollo-Client

If your app uses Apollo-Client, you can also use ErgonoMockedProvider which wraps ergonomock(). The generated values are stable & deterministic based on the query name, shape, and variables (this is so you can leverage testing snapshots if you are so inclined).

See example

import { ErgonoMockedProvider as MockedProvider } from 'graphql-ergonomock';
import schema from '../my-schema.graphql';

test("I can mock a response", () => {
  const mocks = {
    MyCrucialOperation: {
      car: { plateNumber: '123abc' }
    }
  };
  const { findByText } = render(
    <MockedProvider schema={schema} mocks={mocks}>
      <MyApp />
    </MockedProvider>
  );
  expect(await findByText(/'123abc'/)).toBeVisible();
});

If a particular component is called multiple times in the React tree (but with different variables), you can provide a function as value for an operation, and the function will be called with the operation: GraphQLOperation as first and only argument.

See example

import { ErgonoMockedProvider as MockedProvider } from 'graphql-ergonomock';
import schema from '../my-schema.graphql';

test("I can mock a response with a function", () => {
  let cardinality = 0;
  const mocks = {
    MyCrucialOperation: (operation) => ({ plateNumber: `aaa00${cardinality++}` })
  };
  const { findAllByText } = render(
    <MockedProvider schema={schema} mocks={mocks}>
      <MyApp />
    </MockedProvider>
  );
  expect(await findAllByText(/'aaa00'/)).toHaveLength(3);
});

Finally, you can spy on executed operations via the onCall prop.

See example

const spy = jest.fn();
const { findByText } = render(
  <MockedProvider schema={schema} onCall={spy}>
    <MyComponent id="1" />
    <MyComponent id="2" />
    <MyComponent id="3" />
  </MockedProvider>
);

//...
expect(spy.mock.calls).toHaveLength(3);
const { operation, response } = spy.mock.calls[0][0];
expect(operation.variables.id).toEqual("1");

Providing Functions as Resolver in the Mock Shape

You can use functions for any part of the nested mock, and it will be used as a resolver for this field. The typical signature for a resolver is (root, args, context, info) => any.

See example

// ...
const mocks = {
  returnShape: {
    returnInt: 4321,
    nestedShape: (root: any, args: any, ctx: any, info: any) => {
      return {
        returnInt: root.someField ? 1234 : 5678
      };
    }
  }
}
//...

Providing default mock resolver functions

If you have custom scalar types or would like to provide default mock resolver functions for certain types, you can pass your mock functions via the resolvers option.

See example

const schema = gql`
  type Shape = {
    id: ID!
    returnInt: Int
    date: Date
    nestedShape: Shape
  }

  type Query {
    getShape: Shape
  }
`;

const testQuery = gql`
{
  getShape {
    id
    returnInt
    date
    nestedShape {
      date
    }
  }
}
`;

const resp = ergonomock(schema, testQuery, {
  resolvers: {
    Date: () => "2021-04-09"
  }
});
expect(resp.data).toMatchObject({
  id: expect.toBeString(),
  returnInt: expect.toBeNumber(),
  date: '2021-04-09'
  nestedShape {
    date: '2021-04-09'
  }
});

Mocking Errors

You can return or throw errors within the mock shape.

See example

const testQuery = gql`
  {
    getCar {
      id
    }
  }
`;

const resp = ergonomock(schema, testQuery, {
  mocks: {
    getCar: () => { throw new Error("Server Error"); }
    // or simply getCar: new Error("Server Error")
  }
});

console.log(resp.data.getCar); // null
console.log(resp.errors[0]); // { message: "Server Error", ...}

Mocking Mutations

You can mock mutations, but if you are using ergonomock() directly, you'll have to provide the correct variables for the operation in order for it to not fail.

See example

test("Can partially mock mutations", () => {
  const query = /* GraphQL */ `
    mutation SampleQuery($input: ShapeInput!) {
      createShape(input: $input) {
        id
        returnInt
        returnString
      }
    }
  `;

  const resp: any = ergonomock(schema, query, {
    mocks: {
      createShape: { id: "567" }
    },
    variables: {
      input: { someID: "123", someInt: 123 }
    }
  });

  expect(resp.data.createShape).toMatchObject({
    id: "567",
    returnInt: expect.toBeNumber(),
    returnString: expect.toBeString()
  });
});

API

ergonomock()

The ergonomock(schema, query, options) function takes 3 arguments

  1. (required) A GraphQL schema (not in SDL form).
  2. (required) A GraphQL query, either in SDL (string) form, or DocumentNode.
  3. (optional) An option object.
    1. mocks is an object that can partially or fully match the expected response shape.
    2. seed is a string used to seed the random number generator for automocked values.
    3. variables is the variable values object used in the query or mutation.

<ErgonoMockedProvider>

This component's props are very similar to Apollo-Client's MockedProvider. The only differences are:

  • mocks is an object where keys are the operation names and the values are the mocks input that ergonomock() would accept. (i.e. could be empty, or any shape that matches the expected response.)
  • onCall is a handler that gets called by any executed query. The call signature is ({operation: GraphQLOperation, response: any}) => void where response is the full response being returned to that single query. The purpose of onCall is to provide some sort of spy (or jest.fn()) to make assertions on which calls went through, with which variables, and get a handle on the generated values from ergonomock().
  • resolvers is an object where the keys are the gql type and the values are the mock resolver functions. It's designed to allow users to override or provide a default mock function for certain types. (e.g. custom scalar types) The call signature is (root, args, context, info) => any.

Roadmap

See the open issues for a list of proposed features (and known issues).

Contributing

Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are greatly appreciated.

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

License

Distributed under the MIT License. See LICENSE for more information.

Contact

Maintainer: Joel Marcotte (Github @joual)

Project Link: https://github.com/SurveyMonkey/graphql-ergonomock

Acknowledgements

版本与发布记录

@cruglobal/graphql-ergonomock 共发布 4 个版本,首次发布于 2024/10/30;过去 12 个月发布了 0 个版本。

版本发布日期距今
1.2.2latest2024/11/162 年前
1.2.12024/11/012 年前
1.2.0-beta.22024/10/302 年前
1.2.0-beta.12024/10/302 年前

关于 @cruglobal/graphql-ergonomock 的常见问题

@cruglobal/graphql-ergonomock 是什么?

Automatic mocking of GraphQL operations.

如何安装 @cruglobal/graphql-ergonomock?

在项目目录运行 npm install @cruglobal/graphql-ergonomock,或使用 pnpm add / yarn add / bun add。

@cruglobal/graphql-ergonomock 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/cruglobal__graphql-ergonomock 是否存在。

@cruglobal/graphql-ergonomock 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@cruglobal/graphql-ergonomock 可以商用吗?

@cruglobal/graphql-ergonomock 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@cruglobal/graphql-ergonomock 的下载量有多少?

根据 npm 官方下载统计,@cruglobal/graphql-ergonomock 在 2026/10/11 – 2026/11/09 这 30 天内被下载 10,378 次,日均约 346 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@cruglobal/graphql-ergonomock 还在维护吗?

最新版本 1.2.2 发布于 2024/11/16(2 年前);至今共发布 4 个版本,其中过去 12 个月发布了 0 个;首次发布于 2024/10/30。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。