From b99f03fcb8242dd2fd1ac769642c41314679833b Mon Sep 17 00:00:00 2001 From: johnjbarton Date: Wed, 20 Jun 2018 08:33:20 -0700 Subject: [PATCH] fix(events): bind emitters with for..in. (#3059) Fixes #3057 --- lib/events.js | 5 +++-- test/unit/events.spec.js | 24 +++++++++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/lib/events.js b/lib/events.js index 29951849b..6d8280bfc 100644 --- a/lib/events.js +++ b/lib/events.js @@ -33,13 +33,14 @@ function bufferEvents (emitter, eventsToBuffer) { class KarmaEventEmitter extends EventEmitter { bind (object) { - Object.keys(object).forEach((method) => { + for (const method in object) { if (method.startsWith('on') && helper.isFunction(object[method])) { this.on(helper.camelToSnake(method.substr(2)), function () { + // We do not use an arrow function here, to supply the caller as this. object[method].apply(object, Array.from(arguments).concat(this)) }) } - }) + } } emitAsync (name) { diff --git a/test/unit/events.spec.js b/test/unit/events.spec.js index 70defe502..673b97e3f 100644 --- a/test/unit/events.spec.js +++ b/test/unit/events.spec.js @@ -20,34 +20,48 @@ describe('events', () => { var object = null beforeEach(() => { - object = sinon.stub({ + // Note: es6 class instances have non-enumerable prototype properties. + function FB () {}; + FB.prototype = { + onPrototypeBar () {} + } + object = new FB() + Object.assign(object, { onFoo: () => {}, onFooBar: () => {}, - foo: () => {}, - bar: () => {} + foo: () => {} }) + emitter.bind(object) }) it('should register all "on" methods to events', () => { + sinon.spy(object, 'onFoo') emitter.emit('foo') expect(object.onFoo).to.have.been.called + sinon.spy(object, 'onFooBar') emitter.emit('foo_bar') expect(object.onFooBar).to.have.been.called + sinon.spy(object, 'onPrototypeBar') + emitter.emit('prototype_bar') + expect(object.onPrototypeBar).to.have.been.called + + sinon.spy(object, 'foo') expect(object.foo).not.to.have.been.called - expect(object.bar).not.to.have.been.called }) it('should bind methods to the owner object', () => { + sinon.spy(object, 'foo') + sinon.spy(object, 'onFoo') + sinon.spy(object, 'onFooBar') emitter.emit('foo') emitter.emit('foo_bar') expect(object.onFoo).to.have.always.been.calledOn(object) expect(object.onFooBar).to.have.always.been.calledOn(object) expect(object.foo).not.to.have.been.called - expect(object.bar).not.to.have.been.called }) })