What follows is a Jest test in TypeScript. I'm wondering why setImmediate() is required.
The first example is a test that works. Next are various things I've tried that don't work. I'm not understanding the what is going on. The signature for pubsub.publish is:
(method) PubSub.publish(triggerName: string, payload: any): Promise<void>
test.only('subscriptions', async () => {
const document = parse(`
subscription {
create
}
`)
const sub = <AsyncIterator<ExecutionResult>>await subscribe(schema, document);
expect(sub.next).toBeDefined()
// setInterval and process.nextTick also work here:
setImmediate(() => pubsub.publish('CREATE_ONE', { create: "FLUM!" })) // this works
const { value: { errors, data } } = await sub.next()
expect(errors).toBeUndefined()
expect(data).toBeDefined()
expect(data.create).toBe('FLUM!')
}, 10000)
So these are other things I've tried, some after researching answers to similar issues. All these attempts fail with a timeout exception on the test:
test.only('subscriptions', async () => {
// attempt #1: jest.useFakeTimers()
const document = parse(`
subscription {
create
}
`)
const sub = <AsyncIterator<ExecutionResult>>await subscribe(schema, document);
expect(sub.next).toBeDefined()
// #1, cont:
// pubsub.publish('CREATE_ONE', { create: "FLUM!" })
// or...
// await pubsub.publish('CREATE_ONE', { create: "FLUM!" })
// this works, though, like in previous test, but with fake timers:
// setImmediate(() => pubsub.publish('CREATE_ONE', { create: "FLUM!" }))
// attempt #2:
// await pubsub.publish('CREATE_ONE', { create: "FLUM!" })
// attempt #3:
// pubsub.publish('CREATE_ONE', { create: "FLUM!" })
// await new Promise(setImmediate)
// attempt #3a (variant):
// await new Promise((resolve) => setImmediate(resolve));
const { value: { errors, data } } = await sub.next()
expect(errors).toBeUndefined()
expect(data).toBeDefined()
expect(data.create).toBe('FLUM!')
}, 10000)
I understand that setImmediate puts a function in the event loop to be executed immediately after any pending I/O events. I'm not sure why it is needed, because pubsub.publish() returns a Promise that can be handled with an await, but what happens in that case is that the next line, await sub.next() is never called.
My thinking is that there's a setInterval call being made in pubsub.publish(), and setImmediate waits for any pending setInterval events to complete (my understanding is fuzzy on this). Attempts 3 and 3a are mechanisms I found elsewhere to do this, but they don't seem to work in this case.
The question: Why does this test require setImmediate to pass?