Skip to content

Commit

Permalink
feat: new type for validations in route (#2)
Browse files Browse the repository at this point in the history
* feat: new type for validations in route

* feat: added testing fixtures
  • Loading branch information
leartgjoni-voiceflow authored Dec 17, 2019
1 parent 32be2b5 commit 0fb9147
Show file tree
Hide file tree
Showing 7 changed files with 8,701 additions and 13,527 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,7 @@ typings/

# next.js build output
.next

# npm
package-lock.json

128 changes: 128 additions & 0 deletions lib/fixtureGenerator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
'use strict';

const serviceFake = (req, res) => res.json({ done: 'done' });

const { expect } = require('chai');
const sinon = require('sinon');

const _ = require('lodash');

const hasUserPrototype = (obj) => obj.constructor !== Object;

const createFixture = async (serviceManager) => {
const { middlewares, controllers } = serviceManager;

return {
start: () => {},
stop: () => {},
middlewares: _.mapValues(middlewares, (service) =>
_.mapValues(service, (method) => {
if (method.callback) {
const callbackMock = sinon.stub().returns(sinon.stub().callsArg(2));
callbackMock.callback = true;
return callbackMock;
}

const methodStub = sinon.stub().callsArg(2);
methodStub.validations = _.mapValues(method.validations, () => sinon.stub().callsArg(2));

return [...Object.values(methodStub.validations), methodStub];
})
),
controllers: Object.keys(controllers).reduce((result, key) => {
const target = controllers[key];

if (hasUserPrototype(target)) {
result[key] = Object.getOwnPropertyNames(Object.getPrototypeOf(target))
.filter((_key) => _key !== 'constructor')
.reduce((_result, _key) => {
_result[_key] = sinon.stub().callsFake(serviceFake);
return _result;
}, {});
} else {
result[key] = Object.keys(target).reduce((_result, _key) => {
const validations = _.mapValues(controllers[key][_key].validations, () => sinon.stub().callsArg(2));
const controllerStub = sinon.stub().callsFake(serviceFake);
controllerStub.validations = validations;
_result[_key] = [...Object.values(validations), controllerStub];
return _result;
}, {});
}

return result;
}, {}),
clients: { io: { bindEvents: () => {} }, socketio: { attach: () => {} } },
services: { socket: null },
};
};

const checkFixture = (fixture, expected) => {
const { middlewares, controllers } = fixture;

const validations = { middlewares: {}, controllers: {} };

Object.keys(controllers).forEach((controller) => {
if (!(controller in expected.controllers)) expected.controllers[controller] = {};
Object.keys(controllers[controller]).forEach((method) => {
const expressMiddlewares = controllers[controller][method];
const controllerMethod = expressMiddlewares[expressMiddlewares.length - 1];

if (controllerMethod.validations) {
if (!validations.controllers[controller]) validations.controllers[controller] = {};

validations.controllers[controller][method] = _.mapValues(controllerMethod.validations, (stub) => stub.callCount);
}

controllers[controller][method] = controllerMethod.callCount;
if (!(method in expected.controllers[controller])) expected.controllers[controller][method] = 0;
});
});

Object.keys(middlewares).forEach((service) => {
if (!(service in expected.middlewares)) expected.middlewares[service] = {};
Object.keys(middlewares[service]).forEach((method) => {
const expressMiddlewares = middlewares[service][method];
const middlewareMethod = expressMiddlewares[expressMiddlewares.length - 1];

if (middlewareMethod.validations) {
if (!validations.middlewares[service]) validations.middlewares[service] = {};

validations.middlewares[service][method] = _.mapValues(middlewareMethod.validations, (stub) => stub.callCount);
}

if (middlewareMethod.callback) {
middlewares[service][method] = middlewareMethod().callCount;
} else {
middlewares[service][method] = middlewareMethod.callCount;
}
if (!(method in expected.middlewares[service])) expected.middlewares[service][method] = 0;
});
});

// seed the expected object with zeros
// middlewares or controllers
Object.keys(validations).forEach((group) => {
if (!(group in expected.validations)) expected.validations[group] = {};
// class in a middleware or controller
Object.keys(validations[group]).forEach((service) => {
if (!(service in expected.validations[group])) expected.validations[group][service] = {};
// method in a class
Object.keys(validations[group][service]).forEach((method) => {
if (!(method in expected.validations[group][service])) expected.validations[group][service][method] = {};
// validation in a method
Object.keys(validations[group][service][method]).forEach((validation) => {
if (!(validation in expected.validations[group][service][method])) expected.validations[group][service][method][validation] = 0;
});
});
});
});

expect(controllers).to.deep.eql(expected.controllers);
expect(middlewares).to.deep.eql(expected.middlewares);
expect(validations).to.deep.eql(expected.validations);
};

module.exports = {
createFixture,
checkFixture,
};
1 change: 1 addition & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
module.exports = {
ExceptionHandler: require('./exceptionHandler'),
ResponseBuilder: require('./responseBuilder'),
FixtureGenerator: require('./fixtureGenerator'),
};
4 changes: 3 additions & 1 deletion lib/responseBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ module.exports = function ResponseBuilder() {
self.route = (dataPromise, successCodeOverride, failureCodeOverride) => {
if (dataPromise.validations && !dataPromise.validationsApplied) {
dataPromise.validationsApplied = true;
return [...self.route(dataPromise.validations), self.route(self.validationResult), self.route(dataPromise)];
const expressMiddlewares = [...self.route(Object.values(dataPromise.validations)), self.route(self.validationResult), self.route(dataPromise)];
expressMiddlewares.validations = dataPromise.validations;
return expressMiddlewares;
}

if (dataPromise.callback) {
Expand Down
Loading

0 comments on commit 0fb9147

Please sign in to comment.