UNPKG

pattern-emitter

Version:

Event emitters with support for regular expressions

478 lines (358 loc) 13.7 kB
var expect = require('expect.js'); var PatternEmitter = require('../lib/patternEmitter'); var EventEmitter = require('events').EventEmitter; describe('PatternEmitter', function() { var emitter; beforeEach(function() { emitter = new PatternEmitter(); }); it("inherits listeners, once and setMaxListeners from EventEmitter", function() { var methods = ['listeners', 'once', 'setMaxListeners']; methods.forEach(function(method) { expect(PatternEmitter.prototype[method]).to.be(EventEmitter.prototype[method]); }); }); describe('constructor', function() { it('adds an _events property', function() { expect(emitter._events).to.eql({}); }); it('adds a _patternEvents property', function() { expect(emitter._patternEvents).to.eql({}); }); it('adds a _regexes property', function() { expect(emitter._regexes).to.eql({}); }); }); describe('prototype.emit', function() { it('returns false if no listeners match the event', function() { var invoked = false; emitter.on(/^t.*/, function() { invoked = true; }); emitter.on('invalid', function() { invoked = true; }); var result = emitter.emit('noMatch'); expect(invoked).to.be(false); expect(result).to.be(false); }); it('returns true if a listener matches the event', function() { emitter.on('test', function() {}); var result = emitter.emit('test'); expect(result).to.be(true); }); it('returns true if a pattern listener matches the event', function() { emitter.on(/^t.*/, function() {}); var result = emitter.emit('test'); expect(result).to.be(true); }); it('invokes a listener when the event matches its type', function() { var invoked = false; emitter.on('test', function() { invoked = true; }); emitter.emit('test'); expect(invoked).to.be(true); }); it('invokes a listener when the event matches its pattern', function() { var invoked = false; emitter.on(/^t.*/, function() { invoked = true; }); emitter.emit('test'); expect(invoked).to.be(true); }); it('invokes the listener with any additional arguments', function() { var args; emitter.on(/^t\w{3}/, function(arg1, arg2, arg3) { args = [arg1, arg2, arg3]; }); emitter.emit('test', 'arg1', 'arg2', 'arg3'); expect(args).to.eql(['arg1', 'arg2', 'arg3']); }); it('adds an event property to the invoked listener', function() { var event; emitter.on(/^\w{2}/, function() { event = this.event; }); emitter.emit('test'); expect(event).to.eql('test'); }); it('invokes all matching listeners', function() { var x = 0; var y = 0; var z = 0; var listener1 = function() { x++; }; var listener2 = function() { y++; }; var listener3 = function() { z++; }; emitter.on(/t.*/, listener1); emitter.on(/.*/, listener1); emitter.on(/.*/, listener2); emitter.on(/.*/, listener3); emitter.on('test', listener3); emitter.emit('test'); expect(x).to.be(2); expect(y).to.be(1); expect(z).to.be(2); }); it('can be called multiple times', function() { var counter = 0; emitter.on(/[t]/, function() { counter++; }); emitter.emit('test'); expect(counter).to.be(1); emitter.emit('test'); expect(counter).to.be(2); }); }); describe('prototype.once', function() { it('adds a listener that can be invoked at most once', function() { var counter = 0; var listener = function() { counter++; }; emitter.once(/[a-z]/, listener); emitter.emit('test'); emitter.emit('test'); expect(counter).to.be(1); expect(emitter._patternEvents).not.to.have.key('/[a-z]/'); }); }); describe('prototype.addListener', function() { it("throws a TypeError if listener isn't a function", function() { var invalidCall = function() { emitter.addListener(/test/, 'invalid'); }; expect(invalidCall).to.throwException(function (e) { expect(e).to.be.a(TypeError); }); }); it("calls _addListener if type isn't a RegExp", function() { var invoked = false; emitter._addListener = function() { invoked = true; }; emitter.addListener('test', function() {}); expect(invoked).to.be(true); }); it("adds the listener to _events if type isn't a RegExp", function() { var listener = function() {}; emitter.addListener('test', listener); expect(emitter._events).to.have.key('test'); expect(emitter._events['test']).to.be(listener); }); it('adds a pattern listener to the _patternEvents property', function() { var regex = /test*/; var listener = function() {}; emitter.addListener(regex, listener); expect(emitter._patternEvents).to.have.key(String(regex)); expect(emitter._patternEvents[String(regex)]).to.be(listener); }); it('creates a regex and adds it to the _regexes property', function() { var regex = /test*/; emitter.addListener(regex, function() {}); expect(emitter._regexes).to.have.key(String(regex)); expect(emitter._regexes[String(regex)]).to.be.a(RegExp); }); it('handles multiple listeners', function() { var regex1 = /test1*/; var regex2 = /test2*/; var listener1 = function() {}; var listener2 = function() {}; emitter.addListener(regex1, listener1); emitter.addListener(regex2, listener2); expect(emitter._patternEvents[String(regex1)]).to.equal(listener1); expect(emitter._patternEvents[String(regex2)]).to.equal(listener2); }); it('can add multiple listeners for the same pattern', function() { var regex = /test*/; emitter.addListener(regex, function() {}); emitter.addListener(regex, function() {}); expect(emitter._patternEvents[String(regex)]).to.have.length(2); }); it('returns the instance of PatternEmitter', function() { var returned = emitter.addListener(/test*/, function() {}); expect(returned).to.equal(emitter); }); }); describe('prototype.on', function() { it('is an alias for prototype.addListener', function() { expect(emitter.on).to.equal(emitter.addListener); }); }); describe('prototype.removeListener', function() { var listeners; var regexes = [/pattern1/, /pattern2/]; var keys = [String(/pattern1/), String(/pattern2/)]; beforeEach(function() { listeners = []; regexes.forEach(function(regex) { var listener = function() {}; listeners.push(listener); emitter._patternEvents[String(regex)] = listener; emitter._regexes[String(regex)] = regex; }); }); it("throws a TypeError if listener isn't a function", function() { var invalidCall = function() { emitter.removeListener(/test/, 'invalid'); }; expect(invalidCall).to.throwException(function (e) { expect(e).to.be.a(TypeError); }); }); it("calls _removeListener if type isn't a RegExp", function() { var invoked = false; emitter._removeListener = function() { invoked = true; }; emitter.removeListener('test', function() {}); expect(invoked).to.be(true); }); it("removes the listener from _events if type isn't a RegExp", function() { var listener = function() {}; emitter.addListener('test', listener); emitter.removeListener('test', listener); expect(emitter._events).not.to.have.key('test'); }); it("doesn't remove pattern listeners given a string type", function() { var key = String(/pattern1/); emitter.removeListener(key, listeners[0]); expect(emitter._patternEvents).to.have.key(key); }); it('removes the listener from the _patternEvents property', function() { emitter.removeListener(regexes[0], listeners[0]); expect(emitter._patternEvents).not.to.have.key(keys[0]); expect(emitter._patternEvents[keys[1]]).to.be(listeners[1]); }); it("doesn't modify other listeners for the pattern", function() { emitter._patternEvents[keys[0]] = [listeners[0], listeners[1]]; emitter.removeListener(regexes[0], listeners[0]); expect(emitter._patternEvents[keys[0]][0]).to.be(listeners[1]); }); it('removes the regex if no other listeners exist for the pattern', function() { emitter.removeListener(regexes[0], listeners[0]); expect(emitter._regexes).not.to.have.key(regexes[0]); expect(emitter._regexes[regexes[1]]).to.be.a(RegExp); }); it("doesn't modify the regex if other listeners exist for the pattern", function() { emitter._patternEvents[keys[0]] = [listeners[0], listeners[1]]; emitter.removeListener(regexes[0], listeners[0]); expect(emitter._regexes).to.have.key(keys[0]); }); it('returns the instance of PatternEmitter', function() { var returned = emitter.removeListener(keys[0], listeners[0]); expect(returned).to.equal(emitter); }); }); describe('prototype.removeAllListeners', function() { var regex = /.*/; beforeEach(function() { emitter.addListener(regex, function() {}); emitter.addListener(regex, function() {}); }); it('removes all listeners for a given pattern', function() { emitter.removeAllListeners(regex); expect(emitter._patternEvents).not.to.have.key(String(regex)); }); it('deletes the pattern from the _regexes property', function() { emitter.removeAllListeners(regex); expect(emitter._regexes).not.to.have.key(String(regex)); }); it('returns the instance of PatternEmitter', function() { var returned = emitter.removeAllListeners(regex); expect(returned).to.equal(emitter); }); }); describe('prototype.patternListeners', function() { it("throws a TypeError if pattern isn't a RexExp", function() { var invalidCall = function() { PatternEmitter.patternListeners(1); }; expect(invalidCall).to.throwException(function (e) { expect(e).to.be.a(TypeError); }); }); it('returns all listeners for the given pattern', function() { var regex = /.*/; emitter.addListener(regex, function() {}); emitter.addListener(regex, function() {}); var result = emitter.patternListeners(regex); expect(result[0]).to.be(emitter._patternEvents[String(regex)][0]); expect(result[1]).to.be(emitter._patternEvents[String(regex)][1]); }); }); describe('prototype.matchingListeners', function() { it('returns an empty array if no listeners match the event', function() { var result = emitter.matchingListeners(/nonMatching/); expect(result).to.have.length(0); }); it('returns an array with a single listener if only one matches', function() { var listener = function() {}; emitter.addListener(/match/, listener); emitter.addListener(/nonMatch/, function() {}); var result = emitter.matchingListeners('match'); expect(result).to.have.length(1); expect(result).to.eql([listener]); }); it('returns an array with matching listeners across patterns and type', function() { var listener1 = function() {}; var listener2 = function() {}; var listener3 = function() {}; var listener4 = function() {}; var invalidListener1 = function() {}; var invalidListener2 = function() {}; emitter.on(new RegExp('test1'), listener1); emitter.on(new RegExp('test\\d'), listener2); emitter.on(new RegExp('test\\d'), listener3); emitter.on('test1', listener4); emitter.on(/testing/, invalidListener1); emitter.on('test2', invalidListener2); var result = emitter.matchingListeners('test1'); expect(result).to.have.length(4); expect(result).to.contain(listener1, listener2, listener3, listener4); }); }); describe('patternListenerCount', function() { it("throws a TypeError if pattern isn't a RegExp", function() { var invalidCall = function() { PatternEmitter.patternListenerCount(1, function() {}); }; expect(invalidCall).to.throwException(function (e) { expect(e).to.be.a(TypeError); }); }); it('returns the number of listeners for the pattern', function() { emitter.addListener(/.*/, function() {}); emitter.addListener(/.*/, function() {}); var result = PatternEmitter.patternListenerCount(emitter, /.*/); expect(result).to.be(2); }); }); describe('listenerCount', function() { it('returns the number of listeners for the event type', function() { emitter.addListener('test', function() {}); emitter.addListener('test', function() {}); emitter.addListener(/test/, function() {}); var result = PatternEmitter.listenerCount(emitter, 'test'); expect(result).to.be(2); }); }); describe('matchingListenerCount', function() { it('returns the number of matching listeners for the type', function() { emitter.addListener(/.*/, function() {}); emitter.addListener(/\w/, function() {}); emitter.addListener(/\w/, function() {}); emitter.addListener(/z/, function() {}); var result = PatternEmitter.matchingListenerCount(emitter, 'test'); expect(result).to.be(3); }); }); });