Open kettanaito opened 4 years ago
are there any stopgap solutions that you can recommend until this feature is built @kettanaito ?
@hsavit1 as far as I know, GraphQL subscription is an abstraction over WebSocket. Subscriptions support would require a WebSocket support as a pre-requisite (#156). I cannot recommend any solution to achieve that at the moment. WebSocket support is on the roadmap, but I wouldn't expect it any time soon, unless you wish to contribute to it.
I finally followed the advice from apollo and moved from subscription-transport-ws to graphql-ws.
Everything is working and tests even pass, but unfortunately they also spit out ...
Unhandled GraphQL subscription error ApolloError: undefined
at runNextTicks (node:internal/process/task_queues:61:5)
at listOnTimeout (node:internal/timers:528:9)
at processTimers (node:internal/timers:502:7) {
graphQLErrors: [ Event { isTrusted: [Getter] } ],
clientErrors: [],
networkError: null,
extraInfo: undefined
}
With subscription-transport-ws I just had an unhandled GET request, which I could ignore with ...
rest.get(graphql_subscription_uri, (_req, res, ctx) => res(ctx.status(200)))
The best I could come up with so far to have graphql-ws run cleanly was to do this in the client in order to avoid sending to graphql-ws during tests ...
const link = process.env.NODE_ENV === 'test' ? httpLink : split(({ query }) => {
//const link = split(({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
);
}, wsLink, authHttpLink);
And then a handler like this ...
graphql.operation(async (req, res, ctx) => {
const { query } = await req.json();
const definition = getMainDefinition(gql`${query}`);
if (definition.kind !== 'OperationDefinition' || definition.operation !== 'subscription') {
console.error(query);
throw new Error("Not a subscription!");
}
return res(ctx.data({ all: null, possible: null, subscription: null, fields: null }));
}),
This is kind of ugly and I don't like it. There must be a better way to just ignore subscriptions?
Okay, cleaner work around ...
In __mocks__/@apollo/client/link/subscriptions.ts
import { ApolloLink, FetchResult, Observable, Operation } from '@apollo/client/core';
import { print } from 'graphql';
import { Client } from 'graphql-ws';
export class GraphQLWsLink extends ApolloLink {
constructor(private client: Client) {
super();
}
public request(operation: Operation): Observable<FetchResult> {
return new Observable((sink) => {
return this.client.subscribe<FetchResult>(
{ ...operation, query: print(operation.query) },
{
next: sink.next.bind(sink),
complete: sink.complete.bind(sink),
error: () => null
},
);
});
}
}
This is basically just the code for apollo versions < 3.5.10 but with the error function doing nothing.
Then just need the rest.get
handler in my earlier post.
Definitely looking forward to this feature since https://github.com/mswjs/msw/pull/2011 has been merged. 🙂
I'm opening a discussion for the GraphQL subscriptions support at #2352. Please participate, read through the document, and share your thoughts! Those are highly appreciated.
The implementation itself is likely to happen next year. Thanks.
What
I suggest to add support for GraphQL subscriptions (example tutorial from Apollo).
Why
To support all three main GraphQL operations: query, mutation, and subscription.
How
Technical notes