diff --git a/src/observeEvents.test.ts b/src/observeEvents.test.ts index 0bb4cef..9e731c7 100644 --- a/src/observeEvents.test.ts +++ b/src/observeEvents.test.ts @@ -7,6 +7,42 @@ import { getImageTag } from './getImageTag.js'; import { containerStartTimeout } from './testing/containerStartTimeout.js'; import { integrationTimeout } from './testing/integrationTimeout.js'; +// The events of a test are written before it observes them, so they arrive +// at once. A test stops observing once the expected number of events has +// arrived, and fails if they have not arrived within this many milliseconds. +const observeTimeout = 10_000; + +const observeUntil = async ( + observe: (signal: AbortSignal) => AsyncGenerator, + expectedCount: number, +): Promise => { + const events: Event[] = []; + const controller = new AbortController(); + const timer = setTimeout(() => { + controller.abort(); + }, observeTimeout); + + try { + for await (const event of observe(controller.signal)) { + events.push(event); + + if (events.length === expectedCount) { + break; + } + } + } finally { + clearTimeout(timer); + } + + if (events.length < expectedCount) { + throw new Error( + `Observed ${events.length} of ${expectedCount} events within ${observeTimeout} milliseconds.`, + ); + } + + return events; +}; + suite('observeEvents', () => { let container: Container; @@ -72,22 +108,17 @@ suite('observeEvents', () => { await client.writeEvents([firstEvent, secondEvent]); - const controller = new AbortController(); - - setTimeout(() => { - controller.abort(); - }, 100); - - const eventsObserved: Event[] = []; - for await (const event of client.observeEvents( - '/test', - { - recursive: false, - }, - controller.signal, - )) { - eventsObserved.push(event); - } + const eventsObserved = await observeUntil( + signal => + client.observeEvents( + '/test', + { + recursive: false, + }, + signal, + ), + 2, + ); assert.equal(eventsObserved.length, 2); }, @@ -116,22 +147,17 @@ suite('observeEvents', () => { await client.writeEvents([firstEvent, secondEvent]); - const controller = new AbortController(); - - setTimeout(() => { - controller.abort(); - }, 100); - - const eventsObserved: Event[] = []; - for await (const event of client.observeEvents( - '/', - { - recursive: true, - }, - controller.signal, - )) { - eventsObserved.push(event); - } + const eventsObserved = await observeUntil( + signal => + client.observeEvents( + '/', + { + recursive: true, + }, + signal, + ), + 2, + ); assert.equal(eventsObserved.length, 2); }); @@ -159,23 +185,18 @@ suite('observeEvents', () => { await client.writeEvents([firstEvent, secondEvent]); - const controller = new AbortController(); - - setTimeout(() => { - controller.abort(); - }, 100); - - const eventsObserved: Event[] = []; - for await (const event of client.observeEvents( - '/test', - { - recursive: false, - lowerBound: { id: '1', type: 'inclusive' }, - }, - controller.signal, - )) { - eventsObserved.push(event); - } + const eventsObserved = await observeUntil( + signal => + client.observeEvents( + '/test', + { + recursive: false, + lowerBound: { id: '1', type: 'inclusive' }, + }, + signal, + ), + 1, + ); assert.equal(eventsObserved.length, 1); const [eventObserved] = eventsObserved; @@ -206,27 +227,22 @@ suite('observeEvents', () => { await client.writeEvents([firstEvent, secondEvent]); - const controller = new AbortController(); - - setTimeout(() => { - controller.abort(); - }, 100); - - const eventsObserved: Event[] = []; - for await (const event of client.observeEvents( - '/test', - { - recursive: false, - fromLatestEvent: { - subject: '/test', - type: 'io.eventsourcingdb.test.bar', - ifEventIsMissing: 'read-everything', - }, - }, - controller.signal, - )) { - eventsObserved.push(event); - } + const eventsObserved = await observeUntil( + signal => + client.observeEvents( + '/test', + { + recursive: false, + fromLatestEvent: { + subject: '/test', + type: 'io.eventsourcingdb.test.bar', + ifEventIsMissing: 'read-everything', + }, + }, + signal, + ), + 1, + ); assert.equal(eventsObserved.length, 1); const [eventObserved] = eventsObserved;