diff --git a/core/base-service/base.js b/core/base-service/base.js index 742272612830f..352314d8363f0 100644 --- a/core/base-service/base.js +++ b/core/base-service/base.js @@ -267,6 +267,12 @@ class BaseService { throw new Error(`Handler not implemented for ${this.constructor.name}`) } + // Making this an instance method ensures debuggability. + // https://github.com/badges/shields/issues/3784 + _validateServiceData(serviceData) { + Joi.assert(serviceData, serviceDataSchema) + } + _handleError(error) { if (error instanceof NotFound || error instanceof InvalidParameter) { trace.logTrace('outbound', emojic.noGoodWoman, 'Handled error', error) @@ -379,7 +385,7 @@ class BaseService { namedParams, transformedQueryParams ) - Joi.assert(serviceData, serviceDataSchema) + serviceInstance._validateServiceData(serviceData) } catch (error) { serviceError = error } diff --git a/core/base-service/base.spec.js b/core/base-service/base.spec.js index c1619983bf6d8..9acdd90a48587 100644 --- a/core/base-service/base.spec.js +++ b/core/base-service/base.spec.js @@ -192,7 +192,7 @@ describe('BaseService', function() { }) }) - it('Throws a validation error on invalid data', async function() { + context('On invalid data', function() { class ThrowingService extends DummyService { async handle() { return { @@ -200,19 +200,37 @@ describe('BaseService', function() { } } } - try { - await ThrowingService.invoke( - {}, - { handleInternalErrors: false }, - { namedParamA: 'bar.bar.bar' } - ) - expect.fail('Expected to throw') - } catch (e) { - expect(e.name).to.equal('ValidationError') - expect(e.details.map(({ message }) => message)).to.deep.equal([ - '"message" is required', - ]) - } + + it('Throws a validation error on invalid data', async function() { + try { + await ThrowingService.invoke( + {}, + { handleInternalErrors: false }, + { namedParamA: 'bar.bar.bar' } + ) + expect.fail('Expected to throw') + } catch (e) { + expect(e.name).to.equal('ValidationError') + expect(e.details.map(({ message }) => message)).to.deep.equal([ + '"message" is required', + ]) + } + }) + + // Ensure debuggabillity. + // https://github.com/badges/shields/issues/3784 + it('Includes the service class in the stack trace', async function() { + try { + await ThrowingService.invoke( + {}, + { handleInternalErrors: false }, + { namedParamA: 'bar.bar.bar' } + ) + expect.fail('Expected to throw') + } catch (e) { + expect(e.stack).to.include('ThrowingService._validateServiceData') + } + }) }) })