Skip to content

Commit

Permalink
Fix payload parsing for subscriptions (#1148)
Browse files Browse the repository at this point in the history
* Fix payload parsing for subscriptions

* Refactor for instance properties access

* Refactor for instance properties access - renaming variable node

* Add tests for parametrical subscriptions

* Improve naming and destructuring
  • Loading branch information
csuriano23 authored Sep 21, 2022
1 parent ae6efff commit 049a1a8
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 15 deletions.
15 changes: 4 additions & 11 deletions src/subscriptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,13 @@ export class SubscriptionManager {
throw new Error(`Subscription '${name}' is not available`);
}

const { document, operationName, variables } = this.operations.get(name)!;

logger.info(`[Subscription] Start ${id}`, event);

const result = await this.execute({
id,
name,
url: event.url,
document,
operationName,
variables,
variables: event.variables,
contextValue,
});

Expand Down Expand Up @@ -151,22 +147,19 @@ export class SubscriptionManager {

private async execute({
id,
document,
name,
url,
operationName,
variables,
contextValue,
}: {
id: ID;
name: SubscriptionFieldName;
url: string;
document: DocumentNode;
operationName: string;
variables: Record<string, any>;
contextValue: ContextValue;
}) {
const variableNodes = this.operations.get(name)!.variables;
const { document, operationName, variables: variableNodes } = this.operations.get(name)!;

const variableValues = variableNodes.reduce((values, variable) => {
const value = parseVariable({
value: variables[variable.variable.name.value],
Expand All @@ -180,7 +173,7 @@ export class SubscriptionManager {

return {
...values,
[name]: value,
[variable.variable.name.value]: value,
};
}, {});

Expand Down
57 changes: 53 additions & 4 deletions tests/subscriptions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jest.mock('cross-undici-fetch', () => ({

import { fetch } from 'cross-undici-fetch';
import { makeExecutableSchema } from '@graphql-tools/schema';
import { PubSub } from 'graphql-subscriptions';
import { PubSub, withFilter } from 'graphql-subscriptions';
import supertest from 'supertest';
import express from 'express';
import bodyParser from 'body-parser';
Expand All @@ -21,19 +21,23 @@ const delay = (ms: number) => {
const testBook1 = {
id: 'book-id-1',
title: 'Test Book 1',
author: 'Test Author 1',
};
const testBook2 = {
id: 'book-id-2',
title: 'Test Book 2',
author: 'Test Author 2',
};
const BOOK_ADDED = 'BOOK_ADDED';
const typeDefs = /* GraphQL */ `
type Book {
id: ID!
title: String!
author: String!
}
type Subscription {
onBook: Book!
onBook: Book!,
onBookBy(author: String!): Book!
}
type Query {
books: [Book!]
Expand Down Expand Up @@ -75,7 +79,7 @@ test('should start subscriptions', async () => {
'Content-Type': 'application/json',
},
body: JSON.stringify({
data: { onBook: { id: 'book-id-1', title: 'Test Book 1' } },
data: { onBook: { id: 'book-id-1', title: 'Test Book 1', author: 'Test Author 1' } },
}),
});
pubsub.publish(BOOK_ADDED, { onBook: testBook2 });
Expand All @@ -88,7 +92,7 @@ test('should start subscriptions', async () => {
},
body: JSON.stringify({
data: {
onBook: { id: 'book-id-2', title: 'Test Book 2' }
onBook: { id: 'book-id-2', title: 'Test Book 2', author: 'Test Author 2' }
}
}),
});
Expand Down Expand Up @@ -127,3 +131,48 @@ test('should stop subscriptions', async () => {
await delay(1000);
expect(fetch).toBeCalledTimes(1);
});

test('should start subscriptions with parameters', async () => {
(fetch as jest.Mock).mockClear();
const pubsub = new PubSub();
const sofa = useSofa({
basePath: '/api',
schema: makeExecutableSchema({
typeDefs,
resolvers: {
Subscription: {
onBookBy: {
subscribe: withFilter(() => pubsub.asyncIterator(BOOK_ADDED), ( { onBookBy: { author: publishedBy } }, { author: targetAuthor }) => {
return publishedBy === targetAuthor;
}),
},
},
},
}),
});

const app = express();
app.use(bodyParser.json());
app.use('/api', sofa);

const res = await supertest(app)
.post('/api/webhook')
.send({ subscription: 'onBookBy', url: '/bookBy', variables: { author: 'Test Author 1' } })
.expect(200);
expect(res.body).toEqual({ id: expect.any(String) });
pubsub.publish(BOOK_ADDED, { onBookBy: testBook1 });
await delay(1000);
expect(fetch).toBeCalledTimes(1);
expect(fetch).toBeCalledWith('/bookBy', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
data: { onBookBy: { id: 'book-id-1', title: 'Test Book 1', author: 'Test Author 1' } },
}),
});
pubsub.publish(BOOK_ADDED, { onBookBy: testBook2 });
await delay(1000);
expect(fetch).toBeCalledTimes(1);
});

0 comments on commit 049a1a8

Please sign in to comment.