Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/flare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export class Flare<E extends Record<string, any>> {
catch<K extends keyof E>(
event: K,
handler: FlareHandler<E[K]>,
options: FlareCatchOptions = {},
options: FlareCatchOptions<E, K> = {}
): () => void {
if (!this.handlerOptionsStore[event]) {
this.handlerOptionsStore[event] = new Set();
Expand Down Expand Up @@ -173,6 +173,9 @@ export class Flare<E extends Record<string, any>> {
timeout: number | undefined,
handlerOptions: HandlerOptionsPair<E, K>
): Promise<void> {
const shouldRun = !handlerOptions.options.when || handlerOptions.options.when(payload);
if (!shouldRun) return;

try {
if (!timeout) return this.call(handlerOptions.handler, payload);

Expand Down Expand Up @@ -202,5 +205,5 @@ export class Flare<E extends Record<string, any>> {

interface HandlerOptionsPair<E, K extends keyof E> {
handler: FlareHandler<E[K]>;
options: FlareCatchOptions;
options: FlareCatchOptions<E, K>;
};
3 changes: 2 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ export type FlareFireOptions = {
strategy?: FlareFireStrategy;
};

export type FlareCatchOptions = {
export type FlareCatchOptions<E, K extends keyof E> = {
once?: boolean;
when?: (payload: E[K]) => boolean;
};

export type FlareInterceptor<E> = {
Expand Down
43 changes: 43 additions & 0 deletions test/flare.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});