Skip to content
This repository has been archived by the owner on Apr 13, 2023. It is now read-only.

Commit

Permalink
Example of a mutation including tests (#1998)
Browse files Browse the repository at this point in the history
* WIP an example of a mutation including tests

* Completed error example
  • Loading branch information
excitement-engineer authored and hwillson committed Aug 21, 2018
1 parent bac9d8e commit ad9ab43
Show file tree
Hide file tree
Showing 10 changed files with 286 additions and 0 deletions.
21 changes: 21 additions & 0 deletions examples/mutation/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# See https://help.github.com/ignore-files/ for more about ignoring files.

# dependencies
/node_modules

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
22 changes: 22 additions & 0 deletions examples/mutation/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "mutation",
"version": "0.1.0",
"private": true,
"dependencies": {
"apollo-boost": "^0.1.6",
"graphql": "^0.13.2",
"react": "^16.3.2",
"react-dom": "^16.3.2",
"react-scripts": "1.1.4",
"react-apollo": "../../lib"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"devDependencies": {
"react-testing-library": "^3.1.3"
}
}
Binary file added examples/mutation/public/favicon.ico
Binary file not shown.
40 changes: 40 additions & 0 deletions examples/mutation/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
15 changes: 15 additions & 0 deletions examples/mutation/public/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": "./index.html",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
15 changes: 15 additions & 0 deletions examples/mutation/src/__snapshots__/addUser.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders content if the mutation has not been called 1`] = `
<div>
<input
placeholder="Username"
value=""
/>
<button
data-testid="add-user-button"
>
Create new user
</button>
</div>
`;
64 changes: 64 additions & 0 deletions examples/mutation/src/addUser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React from 'react';
import { Mutation } from 'react-apollo';
import { gql } from 'apollo-boost';

export const ADD_USER = gql`
mutation create($username: String!) {
createUser(username: $username) {
id
username
}
}
`;

export default class AddUser extends React.Component {
state = {
username: '',
};
render() {
const { username } = this.state;

return (
<Mutation mutation={ADD_USER} variables={{ username }} onError={() => {}}>
{(addUser, result) => {
const { data, loading, error, called } = result;

if (!called) {
return (
<div>
<input
placeholder="Username"
value={username}
onChange={e => this.setState({ username: e.target.value })}
/>
<button data-testid="add-user-button" onClick={addUser}>
Create new user
</button>
</div>
);
}
if (loading) {
return <div>LOADING</div>;
}
if (error) {
return <div>ERROR</div>;
}

const { createUser } = data;

if (createUser) {
const { username, id } = createUser;

return (
<div>
Created {username} with id {id}
</div>
);
} else {
return null;
}
}}
</Mutation>
);
}
}
86 changes: 86 additions & 0 deletions examples/mutation/src/addUser.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React from 'react';
import { render, Simulate, wait } from 'react-testing-library';
import { MockedProvider } from 'react-apollo/test-utils';

import AddUser, { ADD_USER } from './addUser';

const request = {
query: ADD_USER,
variables: { username: 'peter' },
};

const mocks = [
{
request,
result: {
data: {
createUser: {
id: '1',
username: 'peter',
},
},
},
},
];

const mocksWithError = [
{
request,
error: new Error('Something went wrong'),
},
];

const waitUntilLoadingIsFinished = queryByText =>
wait(() => {
expect(queryByText('LOADING')).toBe(null);
});

it('renders content if the mutation has not been called', () => {
const { container } = render(
<MockedProvider mocks={mocks}>
<AddUser />
</MockedProvider>,
);
expect(container.firstChild).toMatchSnapshot();
});

it('fires the mutation', async () => {
const { container, getByPlaceholderText, getByTestId, getByText, queryByText } = render(
<MockedProvider mocks={mocks} addTypename={false}>
<AddUser />
</MockedProvider>,
);

const inputNode = getByPlaceholderText('Username');
inputNode.value = 'peter';
Simulate.change(inputNode);

const buttonNode = getByTestId('add-user-button');
Simulate.click(buttonNode);

getByText('LOADING');

await waitUntilLoadingIsFinished(queryByText);

getByText('Created peter with id 1');
});

it('errors', async () => {
const { getByTestId, getByText, getByPlaceholderText, queryByText } = render(
<MockedProvider mocks={mocksWithError} addTypename={false}>
<AddUser />
</MockedProvider>,
);

const inputNode = getByPlaceholderText('Username');
inputNode.value = 'peter';
Simulate.change(inputNode);

const buttonNode = getByTestId('add-user-button');

Simulate.click(buttonNode);

await waitUntilLoadingIsFinished(queryByText);

getByText('ERROR');
});
5 changes: 5 additions & 0 deletions examples/mutation/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
body {
margin: 0;
padding: 0;
font-family: sans-serif;
}
18 changes: 18 additions & 0 deletions examples/mutation/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react';
import { render } from 'react-dom';
import ApolloClient from 'apollo-boost';
import { ApolloProvider } from 'react-apollo';

import AddUser from './addUser';

const client = new ApolloClient({
uri: 'https://kqpk9j3kz7.lp.gql.zone/graphql',
});

const WrappedApp = (
<ApolloProvider client={client}>
<AddUser />
</ApolloProvider>
);

render(WrappedApp, document.getElementById('root'));

0 comments on commit ad9ab43

Please sign in to comment.