Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
7 changes: 5 additions & 2 deletions lib/subscription-connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -445,8 +445,11 @@ module.exports = class SubscriptionConnection {

sendError (err, id) {
const convertedError = toGraphQLError(err)
// Graphql over websocket spec requires that errors are wrapped in an array
this.sendMessage(this.protocolMessageTypes.GQL_ERROR, id, [convertedError])
// graphql-transport-ws requires errors wrapped in an array; the legacy
// subscriptions-transport-ws protocol (identified as 'graphql-ws') expects
// a single error object instead.
const payload = this.socket.protocol === 'graphql-ws' ? convertedError : [convertedError]
this.sendMessage(this.protocolMessageTypes.GQL_ERROR, id, payload)
}

async handleConnectionInitExtension (extension) {
Expand Down
3 changes: 2 additions & 1 deletion test/query-depth.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -516,5 +516,6 @@ test('queryDepth - enforce depth limit for subscriptions over websocket', async
const errorMessage = await waitForMessageType('error')

t.assert.strictEqual(errorMessage.id, '1')
t.assert.match(errorMessage.payload[0].message, /Graphql validation error/)
// graphql-ws (subscriptions-transport-ws) sends a single error object, not an array
t.assert.match(errorMessage.payload.message, /Graphql validation error/)
})
34 changes: 34 additions & 0 deletions test/subscription-connection.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -943,3 +943,37 @@ test('should use default protocol when client does not specify a subprotocol', a

ws.close()
})

test('sendError sends a plain object for graphql-ws protocol', async (t) => {
t.plan(2)
const messages = []
const sc = new SubscriptionConnection({
on () {},
close () {},
send (msg, cb) { messages.push(JSON.parse(msg)); cb() },
protocol: GRAPHQL_WS
}, {})

await sc.sendError(new Error('boom'), 1)

t.assert.strictEqual(messages.length, 1)
// legacy graphql-ws expects the payload to be a single error object, not an array
t.assert.ok(!Array.isArray(messages[0].payload), 'payload must not be an array for graphql-ws')
})

test('sendError wraps error in array for graphql-transport-ws protocol', async (t) => {
t.plan(2)
const messages = []
const sc = new SubscriptionConnection({
on () {},
close () {},
send (msg, cb) { messages.push(JSON.parse(msg)); cb() },
protocol: GRAPHQL_TRANSPORT_WS
}, {})

await sc.sendError(new Error('boom'), 1)

t.assert.strictEqual(messages.length, 1)
// graphql-transport-ws spec requires errors wrapped in an array
t.assert.ok(Array.isArray(messages[0].payload), 'payload must be an array for graphql-transport-ws')
})
6 changes: 4 additions & 2 deletions test/subscription-hooks.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,8 @@ test('subscription - should handle preSubscriptionParsing hook errors', async t
t.assert.deepEqual(data, {
id: 1,
type: 'error',
payload: [{ message: 'a preSubscriptionParsing error occurred' }]
// graphql-ws (subscriptions-transport-ws) expects a single error object, not an array
payload: { message: 'a preSubscriptionParsing error occurred' }
})
}
})
Expand Down Expand Up @@ -303,7 +304,8 @@ test('subscription - should handle preSubscriptionExecution hook errors', async
t.assert.deepEqual(data, {
id: 1,
type: 'error',
payload: [{ message: 'a preSubscriptionExecution error occurred' }]
// graphql-ws (subscriptions-transport-ws) expects a single error object, not an array
payload: { message: 'a preSubscriptionExecution error occurred' }
})
}
})
Expand Down
5 changes: 3 additions & 2 deletions test/subscription.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1317,14 +1317,15 @@ test('subscription server sends correct error if execution throws', (t, done) =>
const data = JSON.parse(chunk)

if (data.id === 1 && data.type === 'error') {
// graphql-ws (subscriptions-transport-ws) expects a single error object, not an array
t.assert.strictEqual(chunk, JSON.stringify({
type: 'error',
id: 1,
payload: [{
payload: {
message: 'custom execution error',
locations: [{ line: 3, column: 13 }],
path: ['notificationAdded']
}]
}
}))

client.end()
Expand Down
Loading