-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MockSubscriptionLink doesn't support multiple subscriptions #12128
Comments
That is indeed a rare use case. I believe the best course of action here would be to use a split link to combine two MockSubscriptionLinks into one "combined mock link". |
as a workaround for now i've patched the local version of import { ApolloLink, DocumentNode, FetchResult, Observable, Operation } from '@apollo/client';
import { addTypenameToDocument, print } from '@apollo/client/utilities';
export interface MockedSubscription {
request: Operation;
}
export interface MockedSubscriptionResult {
result?: FetchResult;
error?: Error;
delay?: number;
}
// https://github.com/apollographql/apollo-client/issues/12128
// added similar stuff from MockLink implementatiotwn
// https://github.com/apollographql/apollo-client/blob/9d6c30697859724d9af532956a3b52ba256def89/src/testing/core/mocking/mockLink.ts#L85
export class MockMultipleSubscriptionLink extends ApolloLink {
unsubscribers: any[] = [];
setups: any[] = [];
private observers: { [key: string]: any[] } = {};
request(operation: Operation) {
return new Observable<FetchResult>(observer => {
this.setups.forEach(x => x());
const operationKey = requestToKey(operation.query, true);
if (!this.observers[operationKey]) {
this.observers[operationKey] = [];
}
this.observers[operationKey].push(observer);
return () => {
this.unsubscribers.forEach(x => x());
};
});
}
simulateResult(
result: MockedSubscriptionResult,
{ complete = false, document }: { complete?: boolean; document?: DocumentNode } = {},
) {
setTimeout(() => {
const observers = this.getDocumentObservers(document);
if (!observers.length) throw new Error('subscription torn down');
observers.forEach(observer => {
if (result.result && observer.next) observer.next(result.result);
if (result.error && observer.error) observer.error(result.error);
if (complete && observer.complete) observer.complete();
});
}, result.delay || 0);
}
simulateComplete({ document }: { document?: DocumentNode }) {
const observers = this.getDocumentObservers(document);
if (!observers.length) throw new Error('subscription torn down');
observers.forEach(observer => {
if (observer.complete) observer.complete();
});
}
onSetup(listener: any): void {
this.setups = this.setups.concat([listener]);
}
onUnsubscribe(listener: any): void {
this.unsubscribers = this.unsubscribers.concat([listener]);
}
private getDocumentObservers(document?: DocumentNode): any[] {
const operationKey = document ? requestToKey(document, true) : Object.keys(this.observers)[0];
return this.observers[operationKey];
}
}
function requestToKey(document: DocumentNode, addTypename: Boolean): string {
const queryString = document && print(addTypename ? addTypenameToDocument(document) : document);
const requestKey = { query: queryString };
return JSON.stringify(requestKey);
}
export function mockObservableLink(): MockMultipleSubscriptionLink {
return new MockMultipleSubscriptionLink();
} |
I would say its not entirely that rare. We have 2-3 subscriptions on one page (one for create, one for update, and a third for async operations that is turned on and off as needed) and we're using split links in our tests. Most of our pages don't have any subscriptions at all though. I personally would love to see more documentation around testing strategy and mocking subscription/fragments! Especially with the new fragment masking! :) |
Issue Description
We have a hook that creates 2 subscriptions. Testing it with only one subscription via
MockSubscriptionLink
was fine, but after adding the second one tests are not working anymore.Looking at the code of MockSubscriptionLink it looks like it can't deal with multiple subscriptions: only last
operation
is saved, there is no filtering by subscription in thesimulateResult
andsimulateComplete
methods.Link to Reproduction
Reproduction Steps
No response
@apollo/client
version3.11.9
The text was updated successfully, but these errors were encountered: