UNPKG

event-mixer

Version:
323 lines (256 loc) 12.2 kB
var { mixer, handler } = require('../index'); describe('The application', function() { var cap = (s) => s.slice(0,1).toUpperCase() + s.slice(1); var events = 'creation birth graduation first-job marriage children retirement death eternity'.split(/\s+/); var fnRegs = 'on off'.split(/\s+/); beforeEach(function() { this.listeners = { celebrate: () => null, cry: () => ({ prevent: true }), dance: () => 'Dance!', laugh: () => ({ stop: true, prevent: true }), party: () => ({ stop: true }), rejoice: () => ({ remove: true }), sing: () => 'Sing!', smile: () => 'Smile!', think: () => 'Think!' }; // spies for tests Object.keys(this.listeners).forEach(k => spyOn(this.listeners, k).and.callThrough()); // mixer target, and emitter elements this.target = {}; this.emitter = {}; this.mixer = mixer(this.target, this.emitter); // handlers for all events this.handlers = events.reduce((a,e) => { a[e] = this.mixer.create(e, { name: e }); return a; }, {}); // registration this.handlers.creation.append([this.listeners.rejoice, this.listeners.celebrate]); this.handlers.birth.append([this.listeners.laugh, this.listeners.dance]); this.handlers.graduation.append([this.listeners.party, this.listeners.smile]); this.handlers['first-job'].append(this.listeners.smile); this.handlers.marriage.append(this.listeners.dance); this.handlers.children.append(this.listeners.dance); this.handlers.death.append(this.listeners.cry); this.handlers.retirement.append(this.listeners.laugh); this.handlers.eternity.append([this.listeners.dance, this.listeners.sing, this.listeners.rejoice]); }); it('must expose event manager creation as a function', function() { expect(mixer).toBeFunction(); }); it('must expose event handler creation as a function', function() { expect(handler).toBeFunction(); }); describe('event mixer', function() { fnRegs.forEach(f => { it(`defines .${f}() register method on its target`, function() { expect(this.target[f]).toBeFunction(); }); it('returns target object from the .${f}() register method', function() { expect(this.target[f]('first-job', this.listeners.think)).toBe(this.target); }); }); it('defines .fire() on its emitter', function() { expect(this.emitter.fire).toBeFunction(); }); it('defines individual listener registration methods on its target', function() { events.forEach(e => expect(this.target['on' + cap(e)]).toBeFunction()); }); it('defines individual listener unregistration methods on its target', function() { events.forEach(e => expect(this.target['off' + cap(e)]).toBeFunction()); }); it('defines individual event trigger methods on its emitter', function() { events.forEach(e => expect(this.emitter['fire' + cap(e)]).toBeFunction()); }); it('acknowledges the presence of an existing event handler', function() { events.forEach(e => expect(this.mixer.has(e)).toBe(true)); }); it('acknowledges the absence of a non-existing event', function() { expect(this.mixer.has('illness')).toBe(false); }); it('returns the handler for an existing event', function() { events.forEach(e => expect(this.mixer.event(e)).toBeDefined()); }); it('returns nothing for a non-existing event', function() { expect(this.mixer.event('faxes')).not.toBeDefined(); }); it('returns event names as string array', function() { expect(this.mixer.names()).toBeArrayOfStrings(); }); it('returns original target object', function() { expect(this.mixer.target()).toBe(this.target); }); it('returns original emitter object', function() { expect(this.mixer.emitter()).toBe(this.emitter); }); it('can create new events with the proper register and trigger methods', function() { this.mixer.create('road-trip'); expect(this.mixer.event('road-trip')).toBeDefined(); expect(this.target['onRoad-trip']).toBeFunction(); expect(this.target['offRoad-trip']).toBeFunction(); expect(this.emitter['fireRoad-trip']).toBeFunction(); }); it('can remove existing events and associated register and trigger methods', function() { this.mixer.destroy('retirement'); expect(this.mixer.event('retirement')).not.toBeDefined(); expect(this.target['onRetirement']).not.toBeDefined(); expect(this.target['offRetirement']).not.toBeDefined(); expect(this.emitter['fireRetirement']).not.toBeDefined(); }); it('allows listener to be added to a single event from target', function() { this.target.on('birth', this.listeners.celebrate); expect(this.mixer.event('birth').has(this.listeners.celebrate)).toBe(true); }); it('allows listener to be added to multiple events from target', function() { this.target.on(['birth', 'death'], this.listeners.celebrate); expect(this.mixer.event('birth').has(this.listeners.celebrate)).toBe(true); expect(this.mixer.event('death').has(this.listeners.celebrate)).toBe(true); }); it('allows listener to be removed from a single event from target', function() { this.target.off('death', this.listeners.cry); expect(this.mixer.event('death').has(this.listeners.cry)).toBe(false); }); it('allows listener to be removed from multiple events from target', function() { this.target.off(['eternity', 'marriage'], this.listeners.dance); expect(this.mixer.event('eternity').has(this.listeners.dance)).toBe(false); expect(this.mixer.event('marriage').has(this.listeners.dance)).toBe(false); }); it('allows listener to be added through an individual register method on target', function() { this.target.onMarriage(this.listeners.celebrate); expect(this.mixer.event('marriage').has(this.listeners.celebrate)).toBeDefined(true); }); it('allows listener to be removed through an individual unregister method on target', function() { this.target.offCreation(this.listeners.rejoice); expect(this.mixer.event('creation').has(this.listeners.rejoice)).toBeDefined(false); }); it('allows emitter to fire events successfully', function() { events.forEach(e => { this.emitter['fire' + cap(e)](); expect(this.mixer.event(e).at(0)).toHaveBeenCalled(); }); }); }); describe('event handler', function() { it('acknowledges the presence of an existing listener', function() { expect(this.handlers.creation.has(this.listeners.rejoice)).toBe(true); }); it('acknowledges the absence of a non-existing listener', function() { expect(this.handlers.death.has(this.listeners.rejoice)).toBe(false); }); it('returns an existing listener for a specified index', function() { expect(this.handlers.marriage.at(0)).toBeFunction(); }); it('returns null for an index at which no listener exists', function() { expect(this.handlers.marriage.at(5)).toBeNull(); }); it('allows a listener to be added', function() { this.handlers.marriage.add(this.listeners.celebrate); expect(this.handlers.marriage.has(this.listeners.celebrate)).toBe(true); }); it('allows a listener to be removed', function() { this.handlers.graduation.remove(this.listeners.party); expect(this.handlers.graduation.has(this.listeners.party)).toBe(false); }); it('returns the current number of listeners', function() { expect(this.handlers.graduation.count()).toBe(2); }); it('allows all listeners to be removed', function() { this.handlers.graduation.clear(); expect(this.handlers.graduation.count()).toBe(0); }); it('allows a listener to opt out of notification', function() { this.handlers.creation.fire(); this.handlers.creation.fire(); expect(this.listeners.rejoice).toHaveBeenCalledTimes(1); }); it('allows a listener to stop continued notifications', function() { this.handlers.graduation.fire(); expect(this.listeners.smile).toHaveBeenCalledTimes(0); }); it('allows a listener to request prevention of normal event result', function() { expect(this.handlers.creation.fire()).toBe(true); expect(this.handlers.death.fire()).toBe(false); }); it('allows a listener to request prevention when stopping notifications', function() { expect(this.handlers.birth.fire()).toBe(false); }); it('allows a listener to stop notifications when requesting prevention', function() { this.handlers.birth.fire(); expect(this.listeners.dance).toHaveBeenCalledTimes(0); }); it('returns the index of an included listener', function() { expect(this.handlers.graduation.indexOf(this.listeners.party)).toBeGreaterThanOrEqualTo(0); expect(this.handlers.graduation.indexOf(this.listeners.cry)).not.toBeGreaterThanOrEqualTo(0); }); it('allows a listener to be prepended', function() { this.handlers.birth.unshift(this.listeners.smile); expect(this.handlers.birth.indexOf(this.listeners.smile)).toBe(0); }); it('allows a listener to be appended', function() { this.handlers.birth.push(this.listeners.smile); expect(this.handlers.birth.indexOf(this.listeners.smile)).toBe(this.handlers.birth.count() - 1); }); it('allows multiple listeners to be prepended', function() { this.handlers.children.prepend([this.listeners.smile, this.listeners.rejoice, this.listeners.celebrate]); expect(this.handlers.children.indexOf(this.listeners.smile)).toBe(0); expect(this.handlers.children.indexOf(this.listeners.rejoice)).toBe(1); expect(this.handlers.children.indexOf(this.listeners.celebrate)).toBe(2); }); it('allows multiple listeners to be appended', function() { this.handlers.children.append([this.listeners.smile, this.listeners.rejoice, this.listeners.celebrate]); expect(this.handlers.children.indexOf(this.listeners.smile)).toBe(this.handlers.children.count() - 3); expect(this.handlers.children.indexOf(this.listeners.rejoice)).toBe(this.handlers.children.count() - 2); expect(this.handlers.children.indexOf(this.listeners.celebrate)).toBe(this.handlers.children.count() - 1); }); it('allows filtering and changing of its listeners', function() { var count = this.handlers.eternity.count(); this.handlers.eternity.each(l => l === this.listeners.sing ? null : eo => l(eo)); expect(this.handlers.eternity.count()).toBe(count - 1); expect(this.handlers.eternity.indexOf(this.listeners.sing)).toBe(-1); expect(this.handlers.eternity.indexOf(this.listeners.dance)).toBe(-1); }); }); });