From 45b5a3bbf2634c1acb83fb8caf54697a6cb0a3e5 Mon Sep 17 00:00:00 2001 From: Jerko Steiner Date: Fri, 15 Nov 2019 20:28:13 -0300 Subject: [PATCH] Add TypedEmitter --- src/shared/TypedEmitter.test.ts | 74 +++++++++++++++++++++++++++++++++ src/shared/TypedEmitter.ts | 19 +++++++++ 2 files changed, 93 insertions(+) create mode 100644 src/shared/TypedEmitter.test.ts create mode 100644 src/shared/TypedEmitter.ts diff --git a/src/shared/TypedEmitter.test.ts b/src/shared/TypedEmitter.test.ts new file mode 100644 index 0000000..11b93c8 --- /dev/null +++ b/src/shared/TypedEmitter.test.ts @@ -0,0 +1,74 @@ +import { TypedEmitter } from './TypedEmitter' +import { EventEmitter } from 'events' + +describe('TypedEmitter', () => { + + let stringMock: jest.Mock + let numberMock: jest.Mock + let valueMock: jest.Mock + + beforeEach(() => { + stringMock = jest.fn() + numberMock = jest.fn() + valueMock = jest.fn() + }) + + const listener1 = (arg: string) => { + stringMock(arg) + } + + const listener2 = (arg: number) => { + numberMock(arg) + } + + const listener3 = (arg: Value) => { + valueMock(arg) + } + + interface Value { + a: number + } + + interface Events { + test1: string + test2: number + test3: Value + } + + let emitter: TypedEmitter + beforeEach(() => { + emitter = new EventEmitter() + emitter.addListener('test1', listener1) + emitter.on('test2', listener2) + emitter.once('test3', listener3) + }) + + describe('addListener & on', () => { + it('adds an event emitter', () => { + emitter.emit('test1', 'value') + emitter.emit('test2', 3) + expect(stringMock.mock.calls).toEqual([[ 'value' ]]) + expect(numberMock.mock.calls).toEqual([[ 3 ]]) + }) + }) + + describe('once', () => { + it('adds an event emitter for one use only', () => { + emitter.emit('test3', { a: 1 }) + emitter.emit('test3', { a: 2 }) + expect(valueMock.mock.calls).toEqual([[ { a: 1 } ]]) + }) + }) + + describe('removeListener & off', () => { + it('removes an event listener', () => { + emitter.removeListener('test1', listener1) + emitter.off('test2', listener2) + emitter.emit('test1', 'value') + emitter.emit('test2', 3) + expect(stringMock.mock.calls).toEqual([]) + expect(numberMock.mock.calls).toEqual([]) + }) + }) + +}) diff --git a/src/shared/TypedEmitter.ts b/src/shared/TypedEmitter.ts new file mode 100644 index 0000000..6dd7acb --- /dev/null +++ b/src/shared/TypedEmitter.ts @@ -0,0 +1,19 @@ +import { EventEmitter } from 'events' + +type Callback = (a: A) => void + +// eslint-disable-next-line +type Events = Record + +export interface TypedEmitter +extends EventEmitter { + addListener(t: K, callback: Callback): this + removeListener(t: K, callback: Callback): this + + on(t: K, callback: Callback): this + once(t: K, callback: Callback): this + + off(t: K, callback: Callback): this + + emit(t: K, value: E[K]): boolean +}