Skip to content

Commit

Permalink
feat: apollo-proxy support returning a promise (#760)
Browse files Browse the repository at this point in the history
resloveWith function should be able to handle returning a Promise.
  • Loading branch information
SimeonC authored and ovidiuch committed Jul 24, 2018
1 parent 52a0771 commit ca53b2f
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 14 deletions.
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,11 @@ Once configured, your components enhanced by `react-apollo` will behave as they

Mocking at the fixture level is done by specifying an `apollo` key in your fixture.

The proxy will look for a `resolveWith` or a `failWith` key in order to return the appropriate mock value: this can be an object or a function returning an object.
The proxy will look for a `resolveWith` or a `failWith` key in order to return the appropriate mock value. This mocked return can be one of;

- an object
- a function returning an object
- a function that returns a Promise that either resolves or rejects with an object

See examples below or check [the fixtures defined in the Apollo example](examples/apollo/components/__fixtures__/Author).

Expand Down Expand Up @@ -596,6 +600,26 @@ export default {
};
```

##### Promise response

```js
export default {
component: Author,
props: {
authorId: 123
},
apollo: {
resolveWith: ({ cache, variables, fixture }) => Promise.resolve({
author: {
__typename: 'Author',
id: variables.authorId,
firstName: variables.authorId === 123 ? 'Ovidiu' : 'Xavier'
}
})
}
};
```

##### Named responses

If your fixture's component is enhanced by multiple operations (like a query and a mutation), you can also provide the name of the operation so the proxy knows which response corresponds to which operation.
Expand Down
55 changes: 55 additions & 0 deletions packages/react-cosmos-apollo-proxy/src/__tests__/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -252,4 +252,59 @@ describe('proxy configured with an endpoint', () => {
getWrappedComponent().props().data.error.graphQLErrors
).toMatchObject(resolveWith.errors);
});

it('allows resolveWith to return a promise', async () => {
setupTestWrapper({
proxyConfig: {
endpoint: 'https://xyz'
},
fixture: {
...sampleFixture,
apollo: {
resolveWith: () => Promise.resolve(resolveWith)
}
}
});

// can be async even if data is mocked
await until(() => getWrappedComponent().props().data.loading === false);

expect(getWrappedComponent().props().data.author).toMatchObject(
resolveWith.author
);
});

it('allows resolveWith to reject a promise', async () => {
const resolveWith = {
errors: [
{
path: ['author'],
message: 'Author id 1 not found',
locations: [{ line: 1, column: 0 }]
}
],
data: {
author: null
}
};

setupTestWrapper({
proxyConfig: {
endpoint: 'https://xyz'
},
fixture: {
...sampleFixture,
apollo: {
resolveWith: () => Promise.reject(resolveWith.errors)
}
}
});

// can be async even if data is mocked
await until(() => getWrappedComponent().props().data.loading === false);

expect(
getWrappedComponent().props().data.error.graphQLErrors
).toMatchObject(resolveWith.errors);
});
});
57 changes: 44 additions & 13 deletions packages/react-cosmos-apollo-proxy/src/fixtureLink.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,33 @@
import { ApolloLink, Observable } from 'apollo-link';

function resolveFunctionOrPromise(result, observer) {
// test to see if the result "looks" like a promise
if (typeof result.then === 'function' && typeof result.catch === 'function') {
result
.then(data => {
observer.next({
data
});
})
.catch(errors => {
observer.next({
errors
});
})
.then(() => {
observer.complete();
});
} else {
observer.next({
data: result
});
observer.complete();
}
}

export function createFixtureLink({ apolloFixture, cache, fixture }) {
return new ApolloLink(
({ operationName, variables }) =>
({ operationName, variables, ...others }) =>
new Observable(observer => {
const { failWith, resolveWith } =
apolloFixture[operationName] || apolloFixture;
Expand All @@ -11,19 +36,25 @@ export function createFixtureLink({ apolloFixture, cache, fixture }) {
observer.error(failWith);
}

observer.next({
data:
typeof resolveWith === 'function'
? resolveWith({ cache, variables, fixture })
: resolveWith.data
? resolveWith.data
: resolveWith,
errors:
(typeof resolveWith !== 'function' && resolveWith.errors) ||
undefined
});
if (typeof resolveWith === 'function') {
resolveFunctionOrPromise(
resolveWith({
cache,
variables,
fixture,
operationName,
...others
}),
observer
);
} else {
observer.next({
data: resolveWith.data ? resolveWith.data : resolveWith,
errors: resolveWith.errors
});

observer.complete();
observer.complete();
}
})
);
}

0 comments on commit ca53b2f

Please sign in to comment.