Skip to content

Commit

Permalink
improve DecoratorHandler
Browse files Browse the repository at this point in the history
  • Loading branch information
Uzlopak committed Apr 10, 2024
1 parent fe44b9b commit 3366526
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 8 deletions.
25 changes: 17 additions & 8 deletions lib/handler/decorator-handler.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,44 @@
'use strict'

module.exports = class DecoratorHandler {
#handler

constructor (handler) {
this.handler = handler
if (typeof handler !== 'object' || handler === null) {
throw new TypeError('handler must be an object')
}
this.#handler = handler
}

onConnect (...args) {
return this.handler.onConnect(...args)
return this.#handler.onConnect(...args)
}

onError (...args) {
return this.handler.onError(...args)
return this.#handler.onError(...args)
}

onUpgrade (...args) {
return this.handler.onUpgrade(...args)
return this.#handler.onUpgrade(...args)
}

onResponseStarted (...args) {
return this.#handler.onResponseStarted?.(...args)
}

onHeaders (...args) {
return this.handler.onHeaders(...args)
return this.#handler.onHeaders(...args)
}

onData (...args) {
return this.handler.onData(...args)
return this.#handler.onData(...args)
}

onComplete (...args) {
return this.handler.onComplete(...args)
return this.#handler.onComplete(...args)
}

onBodySent (...args) {
return this.handler.onBodySent(...args)
return this.#handler.onBodySent(...args)
}
}
68 changes: 68 additions & 0 deletions test/decorator-handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
'use strict'

const { tspl } = require('@matteo.collina/tspl')
const { describe, test } = require('node:test')
const DecoratorHandler = require('../lib/handler/decorator-handler')

const methods = [
'onConnect',
'onError',
'onUpgrade',
'onHeaders',
'onResponseStarted',
'onData',
'onComplete',
'onBodySent'
]

describe('DecoratorHandler', () => {
test('should throw if provided handler is not an object', (t) => {
t = tspl(t, { plan: 4 })
t.throws(() => new DecoratorHandler(null), new TypeError('handler must be an object'))
t.throws(() => new DecoratorHandler('string'), new TypeError('handler must be an object'))

t.throws(() => new DecoratorHandler(null), new TypeError('handler must be an object'))
t.throws(() => new DecoratorHandler('string'), new TypeError('handler must be an object'))
})

test('should not expose the handler', (t) => {
t = tspl(t, { plan: 1 })
const handler = {}
const decorator = new DecoratorHandler(handler)
t.strictEqual(Object.keys(decorator).length, 0)
})

methods.forEach((method) => {
test(`should have delegate ${method} method`, (t) => {
t = tspl(t, { plan: 1 })
const decorator = new DecoratorHandler({})
t.equal(typeof decorator[method], 'function')
})

test(`should delegate ${method}`, (t) => {
t = tspl(t, { plan: 1 })
const handler = { [method]: () => method }
const decorator = new DecoratorHandler(handler)
t.equal(decorator[method](), method)
})

test(`should delegate ${method} with arguments`, (t) => {
t = tspl(t, { plan: 1 })
const handler = { [method]: (...args) => args }
const decorator = new DecoratorHandler(handler)
t.deepStrictEqual(decorator[method](1, 2, 3), [1, 2, 3])
})

test(`can be extended and should delegate ${method}`, (t) => {
t = tspl(t, { plan: 1 })

class ExtendedHandler extends DecoratorHandler {
[method] () {
return method
}
}
const decorator = new ExtendedHandler({})
t.equal(decorator[method](), method)
})
})
})

0 comments on commit 3366526

Please sign in to comment.