-
Notifications
You must be signed in to change notification settings - Fork 2k
Subscriptions support #846
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
Changes from 1 commit
18826e1
b8a3c74
74a7dc6
1242665
0dd3ce3
ba0f60e
e989ae5
0d8380f
e3f695c
a76e7a3
54ca988
5f25f53
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,7 @@ import { expect } from 'chai'; | |
import { describe, it } from 'mocha'; | ||
import EventEmitter from 'events'; | ||
import eventEmitterAsyncIterator from './eventEmitterAsyncIterator'; | ||
import {subscribe} from '../subscribe'; | ||
import { subscribe } from '../subscribe'; | ||
import { parse } from '../../language'; | ||
import { | ||
GraphQLSchema, | ||
|
@@ -77,10 +77,7 @@ describe('Subscribe', () => { | |
subscription: SubscriptionType | ||
}); | ||
|
||
it('produces a payload per subscription event', async () => { | ||
|
||
const pubsub = new EventEmitter(); | ||
|
||
const createSubscription = pubsub => { | ||
const data = { | ||
inbox: { | ||
emails: [ | ||
|
@@ -125,13 +122,21 @@ describe('Subscribe', () => { | |
|
||
// GraphQL `subscribe` has the same call signature as `execute`, but returns | ||
// AsyncIterator instead of Promise. | ||
const subscription = subscribe( | ||
emailSchema, | ||
ast, | ||
data, | ||
null, // context | ||
{ priority: 1 } | ||
); | ||
return { | ||
subscription: subscribe( | ||
emailSchema, | ||
ast, | ||
data, | ||
null, // context | ||
{ priority: 1 } | ||
), | ||
sendImportantEmail, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. small thing, but moving this to the first key in this return object would make it more obvious that more than one thing are being returned, otherwise it's easy to mistake this as another argument to subscribe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||
}; | ||
}; | ||
|
||
it('produces a payload per subscription event', async () => { | ||
const pubsub = new EventEmitter(); | ||
const { sendImportantEmail, subscription } = createSubscription(pubsub); | ||
|
||
// Wait for the next subscription payload. | ||
const payload = subscription.next(); | ||
|
@@ -211,4 +216,279 @@ describe('Subscribe', () => { | |
}); | ||
}); | ||
|
||
it('produces a payload when there are multiple events', async () => { | ||
const pubsub = new EventEmitter(); | ||
const { sendImportantEmail, subscription } = createSubscription(pubsub); | ||
let payload = subscription.next(); | ||
|
||
// A new email arrives! | ||
expect(sendImportantEmail({ | ||
from: '[email protected]', | ||
subject: 'Alright', | ||
message: 'Tests are good', | ||
unread: true, | ||
})).to.equal(true); | ||
|
||
expect(await payload).to.deep.equal({ | ||
done: false, | ||
value: { | ||
data: { | ||
importantEmail: { | ||
email: { | ||
from: '[email protected]', | ||
subject: 'Alright', | ||
}, | ||
inbox: { | ||
unread: 1, | ||
total: 2, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}); | ||
|
||
payload = subscription.next(); | ||
|
||
// A new email arrives! | ||
expect(sendImportantEmail({ | ||
from: '[email protected]', | ||
subject: 'Alright 2', | ||
message: 'Tests are good 2', | ||
unread: true, | ||
})).to.equal(true); | ||
|
||
expect(await payload).to.deep.equal({ | ||
done: false, | ||
value: { | ||
data: { | ||
importantEmail: { | ||
email: { | ||
from: '[email protected]', | ||
subject: 'Alright 2', | ||
}, | ||
inbox: { | ||
unread: 2, | ||
total: 3, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}); | ||
}); | ||
|
||
it('should not trigger when subscription is already done', async () => { | ||
const pubsub = new EventEmitter(); | ||
const { sendImportantEmail, subscription } = createSubscription(pubsub); | ||
let payload = subscription.next(); | ||
|
||
// A new email arrives! | ||
expect(sendImportantEmail({ | ||
from: '[email protected]', | ||
subject: 'Alright', | ||
message: 'Tests are good', | ||
unread: true, | ||
})).to.equal(true); | ||
|
||
expect(await payload).to.deep.equal({ | ||
done: false, | ||
value: { | ||
data: { | ||
importantEmail: { | ||
email: { | ||
from: '[email protected]', | ||
subject: 'Alright', | ||
}, | ||
inbox: { | ||
unread: 1, | ||
total: 2, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}); | ||
|
||
payload = subscription.next(); | ||
subscription.return(); | ||
|
||
// A new email arrives! | ||
expect(sendImportantEmail({ | ||
from: '[email protected]', | ||
subject: 'Alright 2', | ||
message: 'Tests are good 2', | ||
unread: true, | ||
})).to.equal(false); | ||
|
||
expect(await payload).to.deep.equal({ | ||
done: true, | ||
value: undefined, | ||
}); | ||
}); | ||
|
||
it('events order is correct when multiple triggered together', async () => { | ||
const pubsub = new EventEmitter(); | ||
const { sendImportantEmail, subscription } = createSubscription(pubsub); | ||
let payload = subscription.next(); | ||
|
||
// A new email arrives! | ||
expect(sendImportantEmail({ | ||
from: '[email protected]', | ||
subject: 'Message', | ||
message: 'Tests are good', | ||
unread: true, | ||
})).to.equal(true); | ||
|
||
// A new email arrives! | ||
expect(sendImportantEmail({ | ||
from: '[email protected]', | ||
subject: 'Message 2', | ||
message: 'Tests are good 2', | ||
unread: true, | ||
})).to.equal(true); | ||
|
||
expect(await payload).to.deep.equal({ | ||
done: false, | ||
value: { | ||
data: { | ||
importantEmail: { | ||
email: { | ||
from: '[email protected]', | ||
subject: 'Message', | ||
}, | ||
inbox: { | ||
unread: 2, | ||
total: 3, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}); | ||
|
||
payload = subscription.next(); | ||
|
||
expect(await payload).to.deep.equal({ | ||
done: false, | ||
value: { | ||
data: { | ||
importantEmail: { | ||
email: { | ||
from: '[email protected]', | ||
subject: 'Message 2', | ||
}, | ||
inbox: { | ||
unread: 2, | ||
total: 3, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}); | ||
}); | ||
|
||
it('invalid query should result in error', async () => { | ||
const invalidAST = parse(` | ||
subscription { | ||
invalidField | ||
} | ||
`); | ||
|
||
expect(() => { | ||
subscribe( | ||
emailSchema, | ||
invalidAST, | ||
null, | ||
null, // context | ||
{ priority: 1 }); | ||
}).to.throw('This subscription is not defined by the schema.'); | ||
}); | ||
|
||
it('throws when subscription definition doesnt return iterator', () => { | ||
const invalidEmailSchema = new GraphQLSchema({ | ||
query: QueryType, | ||
subscription: new GraphQLObjectType({ | ||
name: 'Subscription', | ||
fields: { | ||
importantEmail: { | ||
type: GraphQLString, | ||
resolve: () => 'test', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you mean to test There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another test to add (which will not have correct behavior just yet) is if a subscription resolver returns an error or throws one: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed the first one, and added a test case for the error |
||
}, | ||
} | ||
}) | ||
}); | ||
|
||
const ast = parse(` | ||
subscription { | ||
importantEmail | ||
} | ||
`); | ||
|
||
expect(() => { | ||
subscribe( | ||
invalidEmailSchema, | ||
ast, | ||
null, | ||
null, // context | ||
{ priority: 1 }); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. note: all the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed |
||
}).to.throw('Subscription must return Async Iterable.'); | ||
}); | ||
|
||
it('expects to have subscribe on type definition with iterator', () => { | ||
const pubsub = new EventEmitter(); | ||
const invalidEmailSchema = new GraphQLSchema({ | ||
query: QueryType, | ||
subscription: new GraphQLObjectType({ | ||
name: 'Subscription', | ||
fields: { | ||
importantEmail: { | ||
type: GraphQLString, | ||
subscribe: () => eventEmitterAsyncIterator(pubsub, 'importantEmail') | ||
}, | ||
} | ||
}) | ||
}); | ||
|
||
const ast = parse(` | ||
subscription { | ||
importantEmail | ||
} | ||
`); | ||
|
||
expect(() => { | ||
subscribe( | ||
invalidEmailSchema, | ||
ast, | ||
null, | ||
null, // context | ||
{ priority: 1 }); | ||
}).not.to.throw(); | ||
}); | ||
|
||
it('throws when subscribe does not return a valid iterator', () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this the same test as the one on line 404? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed |
||
const invalidEmailSchema = new GraphQLSchema({ | ||
query: QueryType, | ||
subscription: new GraphQLObjectType({ | ||
name: 'Subscription', | ||
fields: { | ||
importantEmail: { | ||
type: GraphQLString, | ||
subscribe: () => 'test' | ||
}, | ||
} | ||
}) | ||
}); | ||
|
||
const ast = parse(` | ||
subscription { | ||
importantEmail | ||
} | ||
`); | ||
|
||
expect(() => { | ||
subscribe( | ||
invalidEmailSchema, | ||
ast, | ||
null, | ||
null, // context | ||
{ priority: 1 }); | ||
}).to.throw('Subscription must return Async Iterable.'); | ||
}); | ||
}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add another test case with two subscriptions on importantEmail and verify that they both receive the payload? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor style detail: functions defined at the top level we use
function createSubscription(pubsub) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed