Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/dvtng/graphql-automock

Automock GraphQL schemas for better testing
https://github.com/dvtng/graphql-automock

apollo apollo-client graphql mock testing

Last synced: 8 days ago
JSON representation

Automock GraphQL schemas for better testing

Awesome Lists containing this project

README

        

# ⭐️ graphql-automock ⭐️

**Automatically mock GraphQL schemas for better testing.**

Features:

- Automatically and deterministically mock GraphQL schemas
- Mock `react-apollo` for simple UI testing
- Control schema execution to reliably test loading and success states

## Getting started

Install via npm or yarn:

```sh
npm install --save-dev graphql-automock
yarn add --dev graphql-automock
```

## Mocking just the schema

Simply pass your GraphQL type definitions to `mockSchema` and
you're ready to go:

```javascript
import { mockSchema } from "graphql-automock";
import { graphql } from "graphql";

const types = `
type Query {
recentPosts: [Post!]!
}

type Post {
id: ID!
content: String!
likes: Int!
}
`;

const mocked = mockSchema(types);

const query = `{
recentPosts {
id
content
likes
}
}`;

graphql(mocked, query);
```

Without any further configuration, this query will return:

```json
{
"data": {
"recentPosts": [
{
"id": "recentPosts.0.id",
"content": "recentPosts.0.content",
"likes": 2
},
{
"id": "recentPosts.1.id",
"content": "recentPosts.1.content",
"likes": 2
}
]
}
}
```

To understand how these values are derived, see [Default values](#default-values).

## Mocking react-apollo

In addition to schema mocking, `` makes the testing of your UI components much easier.

Wrapping components in a `` allows any `graphql()` and `` components in the tree to receive mock data.
However note that components will first enter a loading state before the query resolves and components re-render.
``, together with a `controller`, allows you to step through GraphQL execution to test both loading and ready states.

```javascript
import { MockApolloProvider, controller } from "graphql-automock";
import TestUtils from "react-dom/test-utils";

it("renders a Post", async () => {
const tree = TestUtils.renderIntoDocument(



);

// Execution is automatically paused, allowing you to test loading state
const spinners = TestUtils.scryRenderedComponentsWithType(tree, Spinner);
expect(spinners).toHaveLength(1);

// Allow schema to run, and wait for it to finish
await controller.run();

// Test success state
const content = TestUtils.scryRenderedComponentsWithType(tree, Content);
expect(content).toHaveLength(1);
});
```

## Customizing mocks

Automatically mocking the entire schema with sensible, deterministic data allows test code to customize _only the data that affects the test_. This results in test code that is more concise and easier to understand:

```javascript
// We're only interested in the behaviour of likes...
it("hides the likes count when there are no likes", () => {
const mocks = {
Post: () => ({
likes: 0 // ...so we only customize that data
})
};

// Using mockSchema
const mockedSchema = mockSchema({
schema: types,
mocks: mocks
});

// Using MockApolloProvider
const mockedElements = (



);

// Continue with test...
});
```

## Mocking errors

Both GraphQL errors and network errors can be mocked.

### Mocking GraphQL errors

Just like with a real GraphQL implementation, GraphQL errors are generated by throwing an error from a (mock) resolver.

```javascript
import { mockSchema } from "graphql-automock";

mockSchema({
schema: types,
mocks: {
Post: () => {
throw new Error("Could not retrieve Post");
}
}
});
```

### Mocking network errors

Since network errors are external to the GraphQL schema, they are simulated through the `controller`.

```javascript
import { MockApolloProvider, controller } from "graphql-automock";
import TestUtils from "react-dom/test-utils";

it("renders a Post", async () => {
const tree = TestUtils.renderIntoDocument(



);

// Test loading state
const spinners = TestUtils.scryRenderedComponentsWithType(tree, Spinner);
expect(spinners).toHaveLength(1);

// Simulate a network error
await controller.run({
networkError: () => new Error("Disconnected")
});

// Test error state
const errorMessage = TestUtils.scryRenderedComponentsWithType(
tree,
ErrorMessage
);
expect(errorMessage).toHaveLength(1);
});
```

## Default values

To ensure that tests are reliable, the values generated by graphql-automock
are 100% deterministic. The following default values are used:

- **Boolean**: `true`
- **Int**: `2`
- **Float**: `3.14`
- **String**: Path to value
- **ID**: Path to value
- **Enum**: The first enum value, sorted alphabetically by name
- **Interface**: The first possible implementation, sorted alphabetically by name
- **Union**: The first possible member type, sorted alphabetically by name
- **List length**: `2`

## API Reference

### mockSchema()

Create a mocked GraphQL schema.

```javascript
function mockSchema(schema: String | GraphQLSchema): GraphQLSchema;

function mockSchema({
schema: String | GraphQLSchema,
mocks: { [String]: MockResolverFn }
}): GraphQLSchema;
```

### mockApolloClient()

Create a mocked Apollo Client.

```javascript
function mockApolloClient(schema: String | GraphQLSchema): ApolloClient;

function mockApolloClient({
schema: String | GraphQLSchema,
mocks: { [String]: MockResolverFn },
controller: Controller
}): ApolloClient;
```

### \

React component that renders a mocked ApolloProvider.

```javascript

```

### type MockResolverFn

```javascript
type MockResolverFn = (parent, args, context, info) => any;
```

### controller

Gives precise control over GraphQL execution, as well as enabling network errors to be simulated.

#### pause()

```javascript
function pause(): void;
```

Pause GraphQL execution until it is explicitly resumed.

_Controller starts in this state._

#### run()

```javascript
function run(): Promise;
function run({ networkError: () => any }): Promise;
```

Resume GraphQL execution if it is paused.

Returns a Promise that resolves when all pending queries have finished executing. If execution was not paused, then it returns a resolved Promise.

If a `networkError` function is provided, pending and subsequent queries will fail with the result of calling that function. The function is called once for each query.