From 1d937d294262d711589ca304624d85d7d9074428 Mon Sep 17 00:00:00 2001 From: Lee Byron Date: Fri, 26 May 2017 17:29:16 -0700 Subject: [PATCH] Subscriptions: Test source errors and execution errors. After discussion in #868, decided that errors emitted from a source event stream should be considered "internal" errors and pass through. However errors encountered during GraphQL execution on a source event should be considered "field" or "query" errors and be represented within that Response. --- src/subscription/__tests__/subscribe-test.js | 130 +++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/src/subscription/__tests__/subscribe-test.js b/src/subscription/__tests__/subscribe-test.js index d15e276fa0..7b73c7832f 100644 --- a/src/subscription/__tests__/subscribe-test.js +++ b/src/subscription/__tests__/subscribe-test.js @@ -714,4 +714,134 @@ describe('Subscribe', () => { await subscription.next() ).to.deep.equal({ value: undefined, done: true }); }); + + it('should handle error during execuction of source event', async () => { + const erroringEmailSchema = emailSchemaWithResolvers( + async function* () { + yield { email: { subject: 'Hello' } }; + yield { email: { subject: 'Goodbye' } }; + yield { email: { subject: 'Bonjour' } }; + }, + event => { + if (event.email.subject === 'Goodbye') { + throw new Error('Never leave.'); + } + return event; + } + ); + + const subscription = subscribe( + erroringEmailSchema, + parse(` + subscription { + importantEmail { + email { + subject + } + } + } + `) + ); + + const payload1 = await subscription.next(); + expect(payload1).to.deep.equal({ + done: false, + value: { + data: { + importantEmail: { + email: { + subject: 'Hello' + } + } + } + } + }); + + // An error in execution is presented as such. + const payload2 = await subscription.next(); + expect(payload2).to.deep.equal({ + done: false, + value: { + errors: [ + { + message: 'Never leave.', + locations: [ { line: 3, column: 11 } ], + path: [ 'importantEmail' ], + } + ], + data: { + importantEmail: null, + } + } + }); + + // However that does not close the response event stream. Subsequent + // events are still executed. + const payload3 = await subscription.next(); + expect(payload3).to.deep.equal({ + done: false, + value: { + data: { + importantEmail: { + email: { + subject: 'Bonjour' + } + } + } + } + }); + + }); + + it('should pass through error thrown in source event stream', async () => { + const erroringEmailSchema = emailSchemaWithResolvers( + async function* () { + yield { email: { subject: 'Hello' } }; + throw new Error('test error'); + }, + email => email + ); + + const subscription = subscribe( + erroringEmailSchema, + parse(` + subscription { + importantEmail { + email { + subject + } + } + } + `) + ); + + const payload1 = await subscription.next(); + expect(payload1).to.deep.equal({ + done: false, + value: { + data: { + importantEmail: { + email: { + subject: 'Hello' + } + } + } + } + }); + + let expectedError; + try { + await subscription.next(); + } catch (error) { + expectedError = error; + } + + expect(expectedError).to.deep.equal(new Error('test error')); + + const payload2 = await subscription.next(); + expect(payload2).to.deep.equal({ + done: true, + value: undefined + }); + }); });