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

Commit

Permalink
add shouldResubscribe option (#389)
Browse files Browse the repository at this point in the history
* add shouldResubscribe option

* refer to pr #389 in changelog
  • Loading branch information
gilesb2 authored and James Baxley committed Jan 5, 2017
1 parent 25c018f commit 92caa83
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 3 deletions.
2 changes: 2 additions & 0 deletions Changelog.md
Expand Up @@ -7,6 +7,8 @@ Expect active development and potentially significant breaking changes in the `0

[PR #391](https://github.com/apollostack/react-apollo/pull/391) gets rid of warnings during redux test.

[PR #389](https://github.com/apollostack/react-apollo/pull/389) added a shouldResubscribe option to allow subscriptions to automatically resubscribe when props change.

### v0.7.2

- Bug: fix issue where changing variables while unskipping didn't result in the variables actually changing - [Issue #374](https://github.com/apollostack/react-apollo/issues/374)
Expand Down
16 changes: 13 additions & 3 deletions src/graphql.tsx
Expand Up @@ -118,6 +118,7 @@ export interface OperationOption {
skip?: boolean | ((props: any) => boolean);
name?: string;
withRef?: boolean;
shouldResubscribe?: (props: any, nextProps: any) => boolean;
}

export default function graphql(
Expand Down Expand Up @@ -212,7 +213,15 @@ export default function graphql(
if (this.type === DocumentType.Mutation) {
return;
};

if (this.type === DocumentType.Subscription
&& operationOptions.shouldResubscribe
&& operationOptions.shouldResubscribe(this.props, nextProps)) {
this.unsubscribeFromQuery();
delete this.queryObservable;
this.updateQuery(nextProps);
this.subscribeToQuery();
return;
}
if (this.shouldSkip(nextProps)) {
if (!this.shouldSkip(this.props)) {
// if this has changed, we better unsubscribe
Expand Down Expand Up @@ -328,7 +337,9 @@ export default function graphql(
// This workaround is only present in Apollo Client 0.4.21
this.queryObservable._setOptionsNoResult(opts);
} else {
this.queryObservable.setOptions(opts);
if (this.queryObservable.setOptions) {
this.queryObservable.setOptions(opts);
}
}
}

Expand Down Expand Up @@ -475,7 +486,6 @@ export default function graphql(
}

if (operationOptions.withRef) mergedPropsAndData.ref = 'wrappedInstance';

this.renderedElement = createElement(WrappedComponent, mergedPropsAndData);
return this.renderedElement;
}
Expand Down
98 changes: 98 additions & 0 deletions test/react-web/client/graphql/subscriptions.test.tsx
Expand Up @@ -10,6 +10,8 @@ declare function require(name: string);
import { mockSubscriptionNetworkInterface } from '../../../../src/test-utils';
import { ApolloProvider, graphql } from '../../../../src';



describe('subscriptions', () => {
const results = ['James Baxley', 'John Pinkerton', 'Sam Clairidge', 'Ben Coleman'].map(
name => ({ result: { user: { name } }, delay: 10 })
Expand Down Expand Up @@ -124,5 +126,101 @@ describe('subscriptions', () => {
);

});
it('resubscribes to a subscription', (done) => {
//we make an extra Hoc which will trigger the inner HoC to resubscribe
//these are the results for the outer subscription
const triggerResults = ['0', 'trigger resubscribe', '3', '4', '5', '6', '7'].map(
trigger => ({ result: { trigger }, delay: 10 })
);
//These are the results fro the resubscription
const results3 = ['NewUser: 1', 'NewUser: 2', 'NewUser: 3', 'NewUser: 4'].map(
name => ({ result: { user: { name } }, delay: 10 })
);


const query = gql`subscription UserInfo { user { name } }`;
const triggerQuery = gql`subscription Trigger { trigger }`;
const networkInterface = mockSubscriptionNetworkInterface(
[
{ request: { query }, results: [...results] },
{ request: { query: triggerQuery }, results: [...triggerResults] },
{ request: { query }, results: [...results3] },
]
);
const client = new ApolloClient({ networkInterface, addTypename: false });
// XXX fix in apollo-client
client.subscribe = client.subscribe.bind(client);

let count = 0;
let unsubscribed = false;
let output;
@graphql(triggerQuery)
@graphql(query, {
shouldResubscribe: (props, nextProps) => {
return nextProps.data.trigger === 'trigger resubscribe';
}
})
class Container extends React.Component<any, any> {
componentWillMount(){
expect(this.props.data.loading).toBeTruthy();
}
componentWillReceiveProps({ data: { loading, user }}) {
// odd counts will be outer wrapper getting subscriptions - ie unchanged
expect(loading).toBeFalsy();
if (count === 0) expect(user).toEqual(results[0].result.user);
if (count === 1) expect(user).toEqual(results[0].result.user);
if (count === 2) expect(user).toEqual(results[1].result.user);
if (count === 3) expect(user).toEqual(results[1].result.user);
if (count <= 1) {
expect(networkInterface.mockedSubscriptionsById[0]).toBeDefined();
}
expect(networkInterface.mockedSubscriptionsById[1]).toBeDefined();
if (count === 2) {
expect(networkInterface.mockedSubscriptionsById[0]).toBeDefined();
//expect(networkInterface.mockedSubscriptionsById[2]).toBeDefined();
}
if (count === 3) {
//it's resubscribed
expect(networkInterface.mockedSubscriptionsById[0]).not.toBeDefined();
expect(networkInterface.mockedSubscriptionsById[2]).toBeDefined();
expect(user).toEqual(results[1].result.user);

}
if (count === 4) {
//it's got result of new subscription
expect(user).toEqual(results3[0].result.user);

}
if (count === 5) {
expect(user).toEqual(results3[0].result.user);
output.unmount();
expect(networkInterface.mockedSubscriptionsById[0]).not.toBeDefined();
expect(networkInterface.mockedSubscriptionsById[1]).not.toBeDefined();
expect(networkInterface.mockedSubscriptionsById[3]).not.toBeDefined();
done();
}

count++;

}
render() {
return null;
}
};

const interval = setInterval(() => {
try {
networkInterface.fireResult(count >2 ? 2 : 0 );
networkInterface.fireResult(1);
}catch (ex) {
clearInterval(interval)
}
if (count > 3) clearInterval(interval);
}, 50);

output = renderer.create(
<ApolloProvider client={client}><Container/></ApolloProvider>
);

});
});

0 comments on commit 92caa83

Please sign in to comment.