Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: makeEventFunctions take an array of parameters #2186

Merged
merged 4 commits into from
Aug 20, 2024
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
2 changes: 1 addition & 1 deletion packages/dashboard/src/PanelEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export const {
listen: listenForPanelOpen,
emit: emitPanelOpen,
useListener: usePanelOpenListener,
} = makeEventFunctions<PanelOpenEventDetail>(PanelEvent.OPEN);
} = makeEventFunctions<[detail: PanelOpenEventDetail]>(PanelEvent.OPEN);

// TODO (#2147): Add the rest of the event functions here. Need to create the correct types for all of them.

Expand Down
103 changes: 83 additions & 20 deletions packages/golden-layout/src/utils/EventUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ describe('EventUtils', () => {

it('makeEmitFunction', () => {
const event = 'test';
const emit = makeEmitFunction(event);
const emit = makeEmitFunction<unknown>(event);
const payload = { test: 'test' };
emit(eventEmitter, payload);
expect(eventEmitter.emit).toHaveBeenCalledWith(event, payload);
Expand Down Expand Up @@ -109,30 +109,93 @@ describe('EventUtils', () => {
});

describe('makeEventFunctions', () => {
const event = 'test';
const { listen, emit, useListener } = makeEventFunctions(event);
const handler = jest.fn();
describe('makeEventFunctions without payload', () => {
const event = 'test';
const { listen, emit, useListener } = makeEventFunctions(event);
const handler = jest.fn();

it('listen', () => {
listen(eventEmitter, handler);
expect(eventEmitter.on).toHaveBeenCalledWith(event, handler);
expect(eventEmitter.off).not.toHaveBeenCalled();
it('listen', () => {
listen(eventEmitter, handler);
expect(eventEmitter.on).toHaveBeenCalledWith(event, handler);
expect(eventEmitter.off).not.toHaveBeenCalled();
});

it('emit', () => {
emit(eventEmitter);
expect(eventEmitter.emit).toHaveBeenCalledWith(event);
});

it('useListener', () => {
const { unmount } = renderHook(() =>
useListener(eventEmitter, handler)
);
expect(eventEmitter.on).toHaveBeenCalledWith(event, handler);
expect(eventEmitter.off).not.toHaveBeenCalled();
jest.clearAllMocks();
unmount();
expect(eventEmitter.on).not.toHaveBeenCalledWith(event, handler);
expect(eventEmitter.off).toHaveBeenCalledWith(event, handler);
});
});
describe('makeEventFunctions with payload', () => {
type Payload = { test: string };
const event = 'test';
const { listen, emit, useListener } = makeEventFunctions<Payload>(event);
const handler = jest.fn();

it('listen', () => {
listen(eventEmitter, handler);
expect(eventEmitter.on).toHaveBeenCalledWith(event, handler);
expect(eventEmitter.off).not.toHaveBeenCalled();
});

it('emit', () => {
const payload: Payload = { test: 'test' };
emit(eventEmitter, payload);
expect(eventEmitter.emit).toHaveBeenCalledWith(event, payload);
});

it('emit', () => {
const payload = { test: 'test' };
emit(eventEmitter, payload);
expect(eventEmitter.emit).toHaveBeenCalledWith(event, payload);
it('useListener', () => {
const { unmount } = renderHook(() =>
useListener(eventEmitter, handler)
);
expect(eventEmitter.on).toHaveBeenCalledWith(event, handler);
expect(eventEmitter.off).not.toHaveBeenCalled();
jest.clearAllMocks();
unmount();
expect(eventEmitter.on).not.toHaveBeenCalledWith(event, handler);
expect(eventEmitter.off).toHaveBeenCalledWith(event, handler);
});
});
describe('makeEventFunctions with multiple parameters', () => {
type Payload = [number, string];
const event = 'test';
const { listen, emit, useListener } = makeEventFunctions<Payload>(event);
const handler = jest.fn();

it('useListener', () => {
const { unmount } = renderHook(() => useListener(eventEmitter, handler));
expect(eventEmitter.on).toHaveBeenCalledWith(event, handler);
expect(eventEmitter.off).not.toHaveBeenCalled();
jest.clearAllMocks();
unmount();
expect(eventEmitter.on).not.toHaveBeenCalledWith(event, handler);
expect(eventEmitter.off).toHaveBeenCalledWith(event, handler);
it('listen', () => {
listen(eventEmitter, handler);
expect(eventEmitter.on).toHaveBeenCalledWith(event, handler);
expect(eventEmitter.off).not.toHaveBeenCalled();
});

it('emit', () => {
const payload: Payload = [1, 'test'];
emit(eventEmitter, ...payload);
expect(eventEmitter.emit).toHaveBeenCalledWith(event, ...payload);
});

it('useListener', () => {
const { unmount } = renderHook(() =>
useListener(eventEmitter, handler)
);
expect(eventEmitter.on).toHaveBeenCalledWith(event, handler);
expect(eventEmitter.off).not.toHaveBeenCalled();
jest.clearAllMocks();
unmount();
expect(eventEmitter.on).not.toHaveBeenCalledWith(event, handler);
expect(eventEmitter.off).toHaveBeenCalledWith(event, handler);
});
});
});
});
53 changes: 29 additions & 24 deletions packages/golden-layout/src/utils/EventUtils.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import EventEmitter from './EventEmitter';
import { useEffect } from 'react';
import EventEmitter from './EventEmitter';

type AsArray<P> = P extends unknown[] ? P : [P];

export type EventHandlerFunction<P = []> = (...parameters: AsArray<P>) => void;
export type EventListenerRemover = () => void;
export type EventListenFunction<TPayload = unknown> = (
export type EventListenFunction<TParameters = []> = (
eventEmitter: EventEmitter,
handler: (p: TPayload) => void
handler: EventHandlerFunction<TParameters>
) => EventListenerRemover;

export type EventEmitFunction<TPayload = unknown> = (
export type EventEmitFunction<TParameters = []> = (
eventEmitter: EventEmitter,
payload: TPayload
...parameters: AsArray<TParameters>
) => void;

export type EventListenerHook<TPayload = unknown> = (
export type EventListenerHook<TParameters = []> = (
eventEmitter: EventEmitter,
handler: (p: TPayload) => void
handler: EventHandlerFunction<TParameters>
) => void;

/**
Expand All @@ -24,35 +27,35 @@ export type EventListenerHook<TPayload = unknown> = (
* @param handler The handler to call when the event is emitted
* @returns A function to stop listening for the event
*/
export function listenForEvent<TPayload>(
export function listenForEvent<TParameters = []>(
eventEmitter: EventEmitter,
event: string,
handler: (p: TPayload) => void
handler: EventHandlerFunction<TParameters>
): EventListenerRemover {
eventEmitter.on(event, handler);
return () => {
eventEmitter.off(event, handler);
};
}

export function makeListenFunction<TPayload>(
export function makeListenFunction<TParameters = []>(
event: string
): EventListenFunction<TPayload> {
): EventListenFunction<TParameters> {
return (eventEmitter, handler) =>
listenForEvent(eventEmitter, event, handler);
}

export function makeEmitFunction<TPayload>(
export function makeEmitFunction<TParameters = []>(
event: string
): EventEmitFunction<TPayload> {
return (eventEmitter, payload) => {
eventEmitter.emit(event, payload);
): EventEmitFunction<TParameters> {
return (eventEmitter, ...parameters) => {
eventEmitter.emit(event, ...parameters);
};
}

export function makeUseListenerFunction<TPayload>(
export function makeUseListenerFunction<TParameters = []>(
event: string
): EventListenerHook<TPayload> {
): EventListenerHook<TParameters> {
return (eventEmitter, handler) => {
useEffect(
() => listenForEvent(eventEmitter, event, handler),
Expand All @@ -66,14 +69,16 @@ export function makeUseListenerFunction<TPayload>(
* @param event Name of the event to create functions for
* @returns Listener, Emitter, and Hook functions for the event
*/
export function makeEventFunctions<TPayload>(event: string): {
listen: EventListenFunction<TPayload>;
emit: EventEmitFunction<TPayload>;
useListener: EventListenerHook<TPayload>;
export function makeEventFunctions<TParameters = []>(
event: string
): {
listen: EventListenFunction<TParameters>;
emit: EventEmitFunction<TParameters>;
useListener: EventListenerHook<TParameters>;
} {
return {
listen: makeListenFunction<TPayload>(event),
emit: makeEmitFunction<TPayload>(event),
useListener: makeUseListenerFunction<TPayload>(event),
listen: makeListenFunction<TParameters>(event),
emit: makeEmitFunction<TParameters>(event),
useListener: makeUseListenerFunction<TParameters>(event),
};
}
Loading