diff --git a/packages/vest-utils/src/__tests__/bus.test.ts b/packages/vest-utils/src/__tests__/bus.test.ts index f5105a793..48d3980d7 100644 --- a/packages/vest-utils/src/__tests__/bus.test.ts +++ b/packages/vest-utils/src/__tests__/bus.test.ts @@ -78,4 +78,50 @@ describe('bus', () => { expect(spy1).not.toHaveBeenCalled(); expect(spy2).toHaveBeenCalled(); }); + + describe('"ANY" wildcard (*)', () => { + it('Should run the wildcard handler on any event', () => { + const bus = createBus(); + const spy1 = jest.fn(); + const spy2 = jest.fn(); + const spy3 = jest.fn(); + bus.on('t1', spy1); + bus.on('t2', spy2); + bus.on('*', spy3); + expect(spy1).not.toHaveBeenCalled(); + expect(spy2).not.toHaveBeenCalled(); + expect(spy3).not.toHaveBeenCalled(); + bus.emit('t1'); + expect(spy1).toHaveBeenCalledTimes(1); + expect(spy2).toHaveBeenCalledTimes(0); + expect(spy3).toHaveBeenCalledTimes(1); + bus.emit('t2'); + expect(spy1).toHaveBeenCalledTimes(1); + expect(spy2).toHaveBeenCalledTimes(1); + expect(spy3).toHaveBeenCalledTimes(2); + }); + + it('Should call the wildcard last, regardless of when it was defined', () => { + const bus = createBus(); + const spy1 = jest.fn(); + const spy2 = jest.fn(); + const spy3 = jest.fn(); + const spy4 = jest.fn(); + bus.on('t1', spy1); + bus.on('*', spy4); + bus.on('t1', spy2); + bus.on('t1', spy3); + bus.emit('t1'); + const invocations = [spy1, spy2, spy3, spy4] + .map(i => i.mock.invocationCallOrder[0]) + .sort(); + + expect(invocations).toEqual([ + spy1.mock.invocationCallOrder[0], + spy2.mock.invocationCallOrder[0], + spy3.mock.invocationCallOrder[0], + spy4.mock.invocationCallOrder[0], + ]); + }); + }); }); diff --git a/packages/vest-utils/src/bus.ts b/packages/vest-utils/src/bus.ts index 3c04c3482..875e37007 100644 --- a/packages/vest-utils/src/bus.ts +++ b/packages/vest-utils/src/bus.ts @@ -1,27 +1,31 @@ import type { CB } from 'utilityTypes'; +const EVENT_WILDCARD = '*'; + export function createBus(): BusType { const listeners: Record = {}; return { emit(event: string, data?: any) { - listener(event).forEach(handler => { - handler(data); - }); + getListeners(event) + .concat(getListeners(EVENT_WILDCARD)) + .forEach(handler => { + handler(data); + }); }, on(event: string, handler: CB): OnReturn { - listeners[event] = listener(event).concat(handler); + listeners[event] = getListeners(event).concat(handler); return { off() { - listeners[event] = listener(event).filter(h => h !== handler); + listeners[event] = getListeners(event).filter(h => h !== handler); }, }; }, }; - function listener(event: string): CB[] { + function getListeners(event: string): CB[] { return listeners[event] || []; } }