Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

### vNEXT

- Fixed format of arguments in backward compatible methods ([PR #74](https://github.com/apollostack/angular2-apollo/pull/74))
- Made queries reusable (use refetch on new variables) ([PR #74](https://github.com/apollostack/angular2-apollo/pull/74))

### v0.4.3

- Added `ApolloModule` (with RC5 of Angular2 comes NgModules) ([PR #63](https://github.com/apollostack/angular2-apollo/pull/63))
Expand Down
29 changes: 20 additions & 9 deletions src/utils/ApolloHandle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@ export class ApolloHandle {

forIn(this.queries(this.component), (options, queryName: string) => {
if (this.hasVariablesChanged(queryName, options.variables)) {
this.createQuery(queryName, options);
if (this.getQuery(queryName)) {
this.reuseQuery(queryName, options);
} else {
this.createQuery(queryName, options);
}
}
});
}
Expand Down Expand Up @@ -163,15 +167,15 @@ export class ApolloHandle {
}

// XXX https://github.com/apollostack/apollo-client/pull/362
private backcompat(queryName: string, method: string, args?) {
private backcompat(queryName: string, method: string, ...args) {
if (this.getQuerySub(queryName)[method]) {
return this.getQuerySub(queryName)[method](...args);
}

return this.getQuery(queryName)[method](...args);
}

private missingCompat(queryName: string, method: string, args?) {
private missingCompat(queryName: string, method: string, ...args) {
if (!this.getQuery(queryName)[method]) {
throw new Error(`Your version of the ApolloClient does not support '${method}'. Try to update.`);
}
Expand All @@ -183,6 +187,11 @@ export class ApolloHandle {
this.component[queryName] = {
errors: null,
loading: true,
unsubscribe: () => this.getQuerySub(queryName).unsubscribe(),
refetch: (...args) => this.backcompat(queryName, 'refetch', ...args),
stopPolling: () => this.backcompat(queryName, 'stopPolling'),
startPolling: (...args) => this.backcompat(queryName, 'startPolling', ...args),
fetchMore: (...args) => this.missingCompat(queryName, 'fetchMore', ...args),
};

const setQuery = ({ errors, loading, data = {} }: any) => {
Expand All @@ -192,11 +201,6 @@ export class ApolloHandle {
errors,
// XXX backwards compatibility of loading property
loading: !!loading,
unsubscribe: () => this.getQuerySub(queryName).unsubscribe(),
refetch: (...args) => this.backcompat(queryName, 'refetch', args),
stopPolling: () => this.backcompat(queryName, 'stopPolling'),
startPolling: (...args) => this.backcompat(queryName, 'startPolling', args),
fetchMore: (...args) => this.missingCompat(queryName, 'fetchMore', args),
}, changed ? data : {});
};

Expand All @@ -205,11 +209,18 @@ export class ApolloHandle {

this.setQuery(queryName, obs);

this.setQuerySub(queryName, obs.subscribe({
this.setQuerySub(queryName, this.getQuery(queryName).subscribe({
next: setQuery,
error(errors) {
setQuery({ errors });
},
}));
}

private reuseQuery(queryName, { variables }) {
// save variables so they can be used in futher comparasion
this.saveVariables(queryName, variables);
// refetch query
this.backcompat(queryName, 'refetch', variables);
}
}
78 changes: 74 additions & 4 deletions tests/ApolloDecorator/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,18 +100,23 @@ describe('Apollo - decorator - queries()', () => {
const component = request({
queries,
client,
});
}) as any;
component.name = variables1.name;

component.ngOnInit();
const refetchSpy = spyOn(component.__apolloHandle.getQuery('data'), 'refetch')
.and.callThrough();

expect(spy.calls.count()).toEqual(1);

component.ngDoCheck();
expect(spy.calls.count()).toEqual(1);
expect(refetchSpy.calls.count()).toEqual(0);

component.name = variables2.name;
component.ngDoCheck();
expect(spy.calls.count()).toEqual(2);
expect(spy.calls.count()).toEqual(1);
expect(refetchSpy.calls.count()).toEqual(1);
});

it('should NOT rebuild query if its variables have not changed', () => {
Expand Down Expand Up @@ -149,22 +154,33 @@ describe('Apollo - decorator - queries()', () => {
const component = request({
queries,
client,
});
}) as any;
component.name = variablesB1.name;
component.id = variablesA.id;

component.ngOnInit();
const refetchASpy = spyOn(component.__apolloHandle.getQuery('dataA'), 'refetch')
.and.callThrough();
const refetchBSpy = spyOn(component.__apolloHandle.getQuery('dataB'), 'refetch')
.and.callThrough();

// should call for two queries
expect(spy.calls.count()).toEqual(2);
expect(refetchASpy.calls.count()).toEqual(0);
expect(refetchBSpy.calls.count()).toEqual(0);

component.ngDoCheck();
// should not call again because there are no changes
expect(spy.calls.count()).toEqual(2);
expect(refetchASpy.calls.count()).toEqual(0);
expect(refetchBSpy.calls.count()).toEqual(0);

component.name = variablesB2.name;
component.ngDoCheck();
// should call just one because only name property has changed
expect(spy.calls.count()).toEqual(3);
expect(spy.calls.count()).toEqual(2);
expect(refetchASpy.calls.count()).toEqual(0);
expect(refetchBSpy.calls.count()).toEqual(1);
});

describe('result object', () => {
Expand Down Expand Up @@ -383,6 +399,60 @@ describe('Apollo - decorator - queries()', () => {
}, 200);
});

// XXX see #73
it('should refetch with new variables instead of resubscribing', (done) => {
const variables1 = { name: 'foo' };
const variables2 = { name: 'bar' };
const queries = (state) => {
return {
data: {
query,
variables: { name: state.name },
},
};
};
const data = {
allHeroes: {
heroes: [{ name: 'Mr Foo' }],
},
};

const client = mockClient({
request: { query, variables: variables1 },
result: { data },
}, {
request: { query, variables: variables2 },
result: { data },
});

const watchQuerySpy = spyOn(client, 'watchQuery').and.callThrough();

const component = request({
queries,
client,
}) as any;
component.name = variables1.name;

component.ngOnInit();

const refetchSpy = spyOn(component.__apolloHandle.getQuery('data'), 'refetch').and.callThrough();

setTimeout(() => {
expect(component.data.allHeroes).toEqual(data.allHeroes);
expect(refetchSpy.calls.count()).toBe(0);
expect(watchQuerySpy.calls.count()).toBe(1);

component.name = variables2.name;
component.ngDoCheck();
setTimeout(() => {
expect(refetchSpy.calls.count()).toBe(1);
expect(watchQuerySpy.calls.count()).toBe(1);
expect(component.data.allHeroes).toEqual(data.allHeroes);
done();
}, 200);
}, 200);
});

function request(options?: any) {
if (!options.client) {
options.client = mockClient(...options.requests);
Expand Down