diff --git a/src/flare.ts b/src/flare.ts index 845b571..66d4431 100644 --- a/src/flare.ts +++ b/src/flare.ts @@ -47,7 +47,7 @@ export class Flare> { catch( event: K, handler: FlareHandler, - options: FlareCatchOptions = {}, + options: FlareCatchOptions = {} ): () => void { if (!this.handlerOptionsStore[event]) { this.handlerOptionsStore[event] = new Set(); @@ -173,6 +173,9 @@ export class Flare> { timeout: number | undefined, handlerOptions: HandlerOptionsPair ): Promise { + const shouldRun = !handlerOptions.options.when || handlerOptions.options.when(payload); + if (!shouldRun) return; + try { if (!timeout) return this.call(handlerOptions.handler, payload); @@ -202,5 +205,5 @@ export class Flare> { interface HandlerOptionsPair { handler: FlareHandler; - options: FlareCatchOptions; + options: FlareCatchOptions; }; diff --git a/src/types.ts b/src/types.ts index f7e2ed9..4439a8e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -13,8 +13,9 @@ export type FlareFireOptions = { strategy?: FlareFireStrategy; }; -export type FlareCatchOptions = { +export type FlareCatchOptions = { once?: boolean; + when?: (payload: E[K]) => boolean; }; export type FlareInterceptor = { diff --git a/test/flare.test.ts b/test/flare.test.ts index 81f0794..8a118c8 100644 --- a/test/flare.test.ts +++ b/test/flare.test.ts @@ -147,4 +147,47 @@ describe('Flare class', () => { // Assert expect(handler).not.toHaveBeenCalled(); }); + + test('handler runs only when when() returns true', async () => { + // Arrange + const handler = jest.fn(); + flare.catch(EVENT_NAME, handler, { when: (payload) => payload === 'run' }); + + // Act + await flare.fire(EVENT_NAME, 'skip'); + await flare.fire(EVENT_NAME, 'run'); + + // Assert + expect(handler).toHaveBeenCalledTimes(1); + expect(handler).toHaveBeenCalledWith('run'); + }); + + test('handler can dynamically run and skip across multiple fires', async () => { + // Arrange + const handler = jest.fn(); + flare.catch(EVENT_NAME, handler, { when: (payload) => payload.active }); + + // Act + await flare.fire(EVENT_NAME, { active: false }); + await flare.fire(EVENT_NAME, { active: true }); + await flare.fire(EVENT_NAME, { active: false }); + await flare.fire(EVENT_NAME, { active: true }); + + // Assert + expect(handler).toHaveBeenCalledTimes(2); + }); + + test('once handlers with when only removed if executed', async () => { + // Arrange + const handler = jest.fn(); + flare.catch(EVENT_NAME, handler, { once: true, when: (payload) => payload.active }); + + // Act + await flare.fire(EVENT_NAME, { active: false }); + await flare.fire(EVENT_NAME, { active: true }); + await flare.fire(EVENT_NAME, { active: true }); + + // Assert + expect(handler).toHaveBeenCalledTimes(1); + }); });