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

https://github.com/rwieruch/react-apollo-async-testing

A lightweight way to test your Mutation and Query components in React Apollo (react-apollo).
https://github.com/rwieruch/react-apollo-async-testing

apollo-client apollo-client-testing react react-apollo react-apollo-testing

Last synced: 6 months ago
JSON representation

A lightweight way to test your Mutation and Query components in React Apollo (react-apollo).

Awesome Lists containing this project

README

          

# react-apollo-async-testing

**Beta:** A lightweight way to test your Mutation and Query components in React Apollo ([react-apollo](https://github.com/apollographql/react-apollo)).

## Install & Usage

On the command line:

`npm install --save-dev react-apollo-async-testing`

The following test examples showcase this library by using [Jest](https://facebook.github.io/jest/) as assertion and test runner library and [Enzyme](http://airbnb.io/enzyme/) for the actual component renderings and utilities. But Enzyme can be replaced by [react-test-renderer](https://www.npmjs.com/package/react-test-renderer) as well.

### API:

```javascript
// creates a Apollo Client with sensible defaults (e.g. apollo-cache-inmemory, apollo-http-link)
// just an optional function, you can create your own Apollo Client instance too
// afterward, client instance can be used in the ApolloProvider
const client = createApolloClient('https://api.github.com/graphql');

// enables GraphQL API mocking
// define the GraphQL endpoint URI
// specify a payload object which has a query (and optional variables and operation name)
// specify a result which you would expect from this query
const promise = stubQueryWith(uri, payload, result);

// injects a spied function into the Mutation(s) component(s)
// check sinon library API to interact with the spy
const sinonSpy = injectSpyInMutation();
```

### Query Testing:

The desired goal is to keep you in control of **what data** should be returned for **which request**. In addition, you need to be in charge to **mimic the different stages** of the request by having control over a promise (e.g. pending request, resolved request).

**In your application:**

```javascript
import React from 'react';
import gql from 'graphql-tag';
import { Query } from 'react-apollo';

import Repository from './Repository';

export const GET_REPOSITORIES_OF_VIEWER = gql`
{
viewer {
name
repositories(last: 25) {
edges {
node {
id
name
url
viewerSubscription
}
}
}
}
}
`;

const App = () => (

{({ data, loading, error }) => {
const { viewer } = data;

if (loading) {
return

Loading ...
;
}

if (error) {
return

Error ...
;
}

if (!viewer) {
return

No data ...
;
}

return (


{viewer.name}


    {viewer.repositories.edges.map(({ node }) => (



  • ))}


);
}}

);

export default App;
```

**In your test:**

```javascript
import React from 'react';
import ReactDOM from 'react-dom';
import { ApolloProvider } from 'react-apollo';

import { mount } from 'enzyme';
import {
createApolloClient,
stubQueryWith,
} from 'react-apollo-async-testing';

import App, { GET_REPOSITORIES_OF_VIEWER } from './App';

let client;
let promise;

const viewerWithRepositories = {
viewer: {
name: 'Robin Wieruch',
repositories: {
edges: [
{
node: {
id: '1',
name: 'bar',
url: 'https://bar.com',
viewerSubscription: 'UNSUBSCRIBED',
},
},
{
node: {
id: '2',
name: 'qwe',
url: 'https://qwe.com',
viewerSubscription: 'UNSUBSCRIBED',
},
},
],
},
},
};

beforeAll(() => {
promise = stubQueryWith(
'https://api.github.com/graphql',
{
query: GET_REPOSITORIES_OF_VIEWER,
},
viewerWithRepositories,
);

client = createApolloClient('https://api.github.com/graphql');
});

afterAll(() => {
// since the fetch API is stubbed with the library
// it has to be restored after the tests
fetch.restore();
});

test('query result of Query component', done => {
const wrapper = mount(


,
);

expect(wrapper.find('[data-test-id="loading"]')).toHaveLength(1);

promise.then().then(() => {
setImmediate(() => {
wrapper.update();

expect(wrapper.find('[data-test-id="profile"]')).toHaveLength(
1,
);
expect(wrapper.find('[data-test-id="profile"]').text()).toEqual(
viewerWithRepositories.viewer.name,
);

done();
});
});
});
```

### Mutation Testing:

The desired goal is to **have a spied function which is used within the Mutation component**'s children as a function to execute the actual mutation. Only then it is possible to make assertions for the executed mutation.

**In your application:**

```javascript
import React from 'react';
import gql from 'graphql-tag';
import { Mutation } from 'react-apollo';

export const WATCH_REPOSITORY = gql`
mutation($id: ID!, $viewerSubscription: SubscriptionState!) {
updateSubscription(
input: { state: $viewerSubscription, subscribableId: $id }
) {
subscribable {
id
viewerSubscription
}
}
}
`;

const VIEWER_SUBSCRIPTIONS = {
SUBSCRIBED: 'SUBSCRIBED',
UNSUBSCRIBED: 'UNSUBSCRIBED',
};

const isWatch = viewerSubscription =>
viewerSubscription === VIEWER_SUBSCRIPTIONS.SUBSCRIBED;

const Repository = ({
repository: { id, url, name, viewerSubscription },
}) => (


{name}


{updateSubscription => (

{isWatch(viewerSubscription) ? 'Unwatch' : 'Watch'}

)}


);

export default Repository;
```

**In your test:**

```javascript
import React from 'react';
import ReactDOM from 'react-dom';
import { ApolloProvider } from 'react-apollo';

import { mount } from 'enzyme';
import {
createApolloClient,
injectSpyInMutation,
} from 'react-apollo-async-testing';

import Repository, { WATCH_REPOSITORY, isWatch } from './Repository';

let client;
let sinonSpy;

beforeAll(() => {
sinonSpy = injectSpyInMutation();

client = createApolloClient('https://api.github.com/graphql');
});

test('interaction with mutation function from the Mutation component', () => {
const repository = {
id: '1',
name: 'foo',
url: 'https://foo.com',
viewerSubscription: 'UNSUBSCRIBED',
};

const wrapper = mount(


,
);

wrapper.find('button').simulate('click');

expect(sinonSpy.calledOnce).toEqual(true);

const expectedObject = {
mutation: WATCH_REPOSITORY,
variables: {
id: repository.id,
viewerSubscription: 'SUBSCRIBED',
},
};

expect(sinonSpy.calledWith(expectedObject)).toEqual(true);
});
```

## Example

A simple example application which uses tested Mutation and Query components can be found in the *example/* folder.

### Install:

* `git clone git@github.com:rwieruch/react-apollo-async-testing.git`
* `cd react-apollo-async-testing/example`
* `npm install`

### Run tests:

* `npm test`

### Run application:

* [add your own REACT_APP_GITHUB_PERSONAL_ACCESS_TOKEN in .env file](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/)
* scopes/permissions you need to check: admin:org, repo, user, notifications
* `npm start`
* visit `http://localhost:3000`