diff --git a/examples/mutation/.gitignore b/examples/mutation/.gitignore
new file mode 100644
index 0000000000..d30f40ef44
--- /dev/null
+++ b/examples/mutation/.gitignore
@@ -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*
diff --git a/examples/mutation/package.json b/examples/mutation/package.json
new file mode 100644
index 0000000000..0a6f34f1d9
--- /dev/null
+++ b/examples/mutation/package.json
@@ -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"
+ }
+}
diff --git a/examples/mutation/public/favicon.ico b/examples/mutation/public/favicon.ico
new file mode 100644
index 0000000000..a11777cc47
Binary files /dev/null and b/examples/mutation/public/favicon.ico differ
diff --git a/examples/mutation/public/index.html b/examples/mutation/public/index.html
new file mode 100644
index 0000000000..ed0ebafa1b
--- /dev/null
+++ b/examples/mutation/public/index.html
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+ React App
+
+
+
+
+
+
+
diff --git a/examples/mutation/public/manifest.json b/examples/mutation/public/manifest.json
new file mode 100644
index 0000000000..ef19ec243e
--- /dev/null
+++ b/examples/mutation/public/manifest.json
@@ -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"
+}
diff --git a/examples/mutation/src/__snapshots__/addUser.test.js.snap b/examples/mutation/src/__snapshots__/addUser.test.js.snap
new file mode 100644
index 0000000000..5a38ad8909
--- /dev/null
+++ b/examples/mutation/src/__snapshots__/addUser.test.js.snap
@@ -0,0 +1,15 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders content if the mutation has not been called 1`] = `
+
+
+
+
+`;
diff --git a/examples/mutation/src/addUser.js b/examples/mutation/src/addUser.js
new file mode 100644
index 0000000000..e394219c8f
--- /dev/null
+++ b/examples/mutation/src/addUser.js
@@ -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 (
+ {}}>
+ {(addUser, result) => {
+ const { data, loading, error, called } = result;
+
+ if (!called) {
+ return (
+
+ this.setState({ username: e.target.value })}
+ />
+
+
+ );
+ }
+ if (loading) {
+ return LOADING
;
+ }
+ if (error) {
+ return ERROR
;
+ }
+
+ const { createUser } = data;
+
+ if (createUser) {
+ const { username, id } = createUser;
+
+ return (
+
+ Created {username} with id {id}
+
+ );
+ } else {
+ return null;
+ }
+ }}
+
+ );
+ }
+}
diff --git a/examples/mutation/src/addUser.test.js b/examples/mutation/src/addUser.test.js
new file mode 100644
index 0000000000..1c1995c459
--- /dev/null
+++ b/examples/mutation/src/addUser.test.js
@@ -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(
+
+
+ ,
+ );
+ expect(container.firstChild).toMatchSnapshot();
+});
+
+it('fires the mutation', async () => {
+ const { container, getByPlaceholderText, getByTestId, getByText, queryByText } = render(
+
+
+ ,
+ );
+
+ 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(
+
+
+ ,
+ );
+
+ const inputNode = getByPlaceholderText('Username');
+ inputNode.value = 'peter';
+ Simulate.change(inputNode);
+
+ const buttonNode = getByTestId('add-user-button');
+
+ Simulate.click(buttonNode);
+
+ await waitUntilLoadingIsFinished(queryByText);
+
+ getByText('ERROR');
+});
diff --git a/examples/mutation/src/index.css b/examples/mutation/src/index.css
new file mode 100644
index 0000000000..b4cc7250b9
--- /dev/null
+++ b/examples/mutation/src/index.css
@@ -0,0 +1,5 @@
+body {
+ margin: 0;
+ padding: 0;
+ font-family: sans-serif;
+}
diff --git a/examples/mutation/src/index.js b/examples/mutation/src/index.js
new file mode 100644
index 0000000000..d2cf72547b
--- /dev/null
+++ b/examples/mutation/src/index.js
@@ -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 = (
+
+
+
+);
+
+render(WrappedApp, document.getElementById('root'));