Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
9a231f0685 |
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hapi-sequelize-crud",
|
"name": "hapi-sequelize-crud",
|
||||||
"version": "2.6.2",
|
"version": "2.6.1",
|
||||||
"description": "Hapi plugin that automatically generates RESTful API for CRUD",
|
"description": "Hapi plugin that automatically generates RESTful API for CRUD",
|
||||||
"main": "build/index.js",
|
"main": "build/index.js",
|
||||||
"config": {
|
"config": {
|
||||||
@ -10,8 +10,8 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "eslint src",
|
"lint": "eslint src",
|
||||||
"test": "ava --require babel-register --source='src/**/*.js' --source='!build/**/*' --tap=${CI-false} src/**/*.test.js | $(if [ -z ${CI:-} ]; then echo 'tail'; else tap-xunit > $CIRCLE_TEST_REPORTS/ava/ava.xml; fi;)",
|
"test": "ava --require babel-register --source='*.test.js' --tap=${CI-false} | $(if [ -z ${CI:-} ]; then echo 'tail'; else tap-xunit > $CIRCLE_TEST_REPORTS/ava/ava.xml; fi;)",
|
||||||
"tdd": "ava --require babel-register --source='src/**/*.js' --source='!build/**/*' --watch src/**/*.test.js",
|
"tdd": "ava --require babel-register --source='*.test.js' --watch",
|
||||||
"build": "scripty",
|
"build": "scripty",
|
||||||
"watch": "scripty"
|
"watch": "scripty"
|
||||||
},
|
},
|
||||||
@ -31,7 +31,6 @@
|
|||||||
"babel-plugin-transform-decorators-legacy": "^1.3.4",
|
"babel-plugin-transform-decorators-legacy": "^1.3.4",
|
||||||
"babel-plugin-transform-es2015-modules-commonjs": "^6.14.0",
|
"babel-plugin-transform-es2015-modules-commonjs": "^6.14.0",
|
||||||
"babel-preset-stage-1": "^6.13.0",
|
"babel-preset-stage-1": "^6.13.0",
|
||||||
"babel-register": "^6.14.0",
|
|
||||||
"eslint": "^3.4.0",
|
"eslint": "^3.4.0",
|
||||||
"eslint-config-pichak": "^1.1.2",
|
"eslint-config-pichak": "^1.1.2",
|
||||||
"eslint-plugin-ava": "^3.0.0",
|
"eslint-plugin-ava": "^3.0.0",
|
||||||
|
45
src/crud.js
45
src/crud.js
@ -14,7 +14,6 @@ const createAll = ({
|
|||||||
config,
|
config,
|
||||||
attributeValidation,
|
attributeValidation,
|
||||||
associationValidation,
|
associationValidation,
|
||||||
scopes,
|
|
||||||
}) => {
|
}) => {
|
||||||
Object.keys(methods).forEach((method) => {
|
Object.keys(methods).forEach((method) => {
|
||||||
methods[method]({
|
methods[method]({
|
||||||
@ -26,7 +25,6 @@ const createAll = ({
|
|||||||
attributeValidation,
|
attributeValidation,
|
||||||
associationValidation,
|
associationValidation,
|
||||||
config,
|
config,
|
||||||
scopes,
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -66,8 +64,6 @@ export default (server, model, { prefix, defaultConfig: config, models: permissi
|
|||||||
include: joi.array().items(joi.string().valid(...modelAssociations)),
|
include: joi.array().items(joi.string().valid(...modelAssociations)),
|
||||||
};
|
};
|
||||||
|
|
||||||
const scopes = Object.keys(model.options.scopes);
|
|
||||||
|
|
||||||
// if we don't have any permissions set, just create all the methods
|
// if we don't have any permissions set, just create all the methods
|
||||||
if (!permissions) {
|
if (!permissions) {
|
||||||
createAll({
|
createAll({
|
||||||
@ -77,7 +73,6 @@ export default (server, model, { prefix, defaultConfig: config, models: permissi
|
|||||||
config,
|
config,
|
||||||
attributeValidation,
|
attributeValidation,
|
||||||
associationValidation,
|
associationValidation,
|
||||||
scopes,
|
|
||||||
});
|
});
|
||||||
// if permissions are set, but we can't parse them, throw an error
|
// if permissions are set, but we can't parse them, throw an error
|
||||||
} else if (!Array.isArray(permissions)) {
|
} else if (!Array.isArray(permissions)) {
|
||||||
@ -92,7 +87,6 @@ export default (server, model, { prefix, defaultConfig: config, models: permissi
|
|||||||
config,
|
config,
|
||||||
attributeValidation,
|
attributeValidation,
|
||||||
associationValidation,
|
associationValidation,
|
||||||
scopes,
|
|
||||||
});
|
});
|
||||||
// if we've gotten here, we have complex permissions and need to set them
|
// if we've gotten here, we have complex permissions and need to set them
|
||||||
} else {
|
} else {
|
||||||
@ -114,7 +108,6 @@ export default (server, model, { prefix, defaultConfig: config, models: permissi
|
|||||||
method,
|
method,
|
||||||
attributeValidation,
|
attributeValidation,
|
||||||
associationValidation,
|
associationValidation,
|
||||||
scopes,
|
|
||||||
config: permissionConfig,
|
config: permissionConfig,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
@ -126,7 +119,6 @@ export default (server, model, { prefix, defaultConfig: config, models: permissi
|
|||||||
prefix,
|
prefix,
|
||||||
attributeValidation,
|
attributeValidation,
|
||||||
associationValidation,
|
associationValidation,
|
||||||
scopes,
|
|
||||||
config: permissionConfig,
|
config: permissionConfig,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -178,11 +170,19 @@ export const get = ({ server, model, prefix = '/', config }) => {
|
|||||||
|
|
||||||
reply(instance.toJSON());
|
reply(instance.toJSON());
|
||||||
},
|
},
|
||||||
config,
|
config: _.defaultsDeep(config, {
|
||||||
|
validate: {
|
||||||
|
params: {
|
||||||
|
id: joi.any(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const scope = ({ server, model, prefix = '/', config }) => {
|
export const scope = ({ server, model, prefix = '/', config }) => {
|
||||||
|
const scopes = Object.keys(model.options.scopes);
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
path: path.join(prefix, model._plural, '{scope}'),
|
path: path.join(prefix, model._plural, '{scope}'),
|
||||||
@ -198,7 +198,13 @@ export const scope = ({ server, model, prefix = '/', config }) => {
|
|||||||
|
|
||||||
reply(list.map((item) => item.toJSON()));
|
reply(list.map((item) => item.toJSON()));
|
||||||
},
|
},
|
||||||
config,
|
config: _.defaultsDeep(config, {
|
||||||
|
validate: {
|
||||||
|
params: {
|
||||||
|
scope: joi.string().valid(...scopes),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -262,6 +268,8 @@ export const destroyAll = ({ server, model, prefix = '/', config }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const destroyScope = ({ server, model, prefix = '/', config }) => {
|
export const destroyScope = ({ server, model, prefix = '/', config }) => {
|
||||||
|
const scopes = Object.keys(model.options.scopes);
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
path: path.join(prefix, model._plural, '{scope}'),
|
path: path.join(prefix, model._plural, '{scope}'),
|
||||||
@ -280,7 +288,13 @@ export const destroyScope = ({ server, model, prefix = '/', config }) => {
|
|||||||
const listAsJSON = list.map((item) => item.toJSON());
|
const listAsJSON = list.map((item) => item.toJSON());
|
||||||
reply(listAsJSON.length === 1 ? listAsJSON[0] : listAsJSON);
|
reply(listAsJSON.length === 1 ? listAsJSON[0] : listAsJSON);
|
||||||
},
|
},
|
||||||
config,
|
config: _.defaultsDeep(config, {
|
||||||
|
validate: {
|
||||||
|
params: {
|
||||||
|
scope: joi.string().valid(...scopes),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -301,7 +315,14 @@ export const update = ({ server, model, prefix = '/', config }) => {
|
|||||||
reply(instance.toJSON());
|
reply(instance.toJSON());
|
||||||
},
|
},
|
||||||
|
|
||||||
config,
|
config: _.defaultsDeep(config, {
|
||||||
|
validate: {
|
||||||
|
payload: joi.object().required(),
|
||||||
|
params: {
|
||||||
|
id: joi.any(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,15 +1,6 @@
|
|||||||
import { set, get } from 'lodash';
|
import { defaultsDeep } from 'lodash';
|
||||||
import joi from 'joi';
|
import joi from 'joi';
|
||||||
|
|
||||||
// if the custom validation is a joi object we need to concat
|
|
||||||
// else, assume it's an plain object and we can just add it in with .keys
|
|
||||||
const concatToJoiObject = (joi, candidate) => {
|
|
||||||
if (!candidate) return joi;
|
|
||||||
else if (candidate.isJoi) return joi.concat(candidate);
|
|
||||||
else return joi.keys(candidate);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export const sequelizeOperators = {
|
export const sequelizeOperators = {
|
||||||
$and: joi.any(),
|
$and: joi.any(),
|
||||||
$or: joi.any(),
|
$or: joi.any(),
|
||||||
@ -56,81 +47,41 @@ export const payloadMethods = [
|
|||||||
'update',
|
'update',
|
||||||
];
|
];
|
||||||
|
|
||||||
export const scopeParamsMethods = [
|
export default ({ method, attributeValidation, associationValidation, config = {} }) => {
|
||||||
'destroyScope',
|
|
||||||
'scope',
|
|
||||||
];
|
|
||||||
|
|
||||||
export const idParamsMethods = [
|
|
||||||
'get',
|
|
||||||
'update',
|
|
||||||
];
|
|
||||||
|
|
||||||
export default ({
|
|
||||||
method, attributeValidation, associationValidation, scopes = [], config = {},
|
|
||||||
}) => {
|
|
||||||
const hasWhere = whereMethods.includes(method);
|
const hasWhere = whereMethods.includes(method);
|
||||||
const hasInclude = includeMethods.includes(method);
|
const hasInclude = includeMethods.includes(method);
|
||||||
const hasPayload = payloadMethods.includes(method);
|
const hasPayload = payloadMethods.includes(method);
|
||||||
const hasScopeParams = scopeParamsMethods.includes(method);
|
const methodConfig = { ...config };
|
||||||
const hasIdParams = idParamsMethods.includes(method);
|
|
||||||
// clone the config so we don't modify it on multiple passes.
|
|
||||||
let methodConfig = { ...config, validate: { ...config.validate } };
|
|
||||||
|
|
||||||
if (hasWhere) {
|
if (hasWhere) {
|
||||||
const query = concatToJoiObject(joi.object()
|
defaultsDeep(methodConfig, {
|
||||||
.keys({
|
validate: {
|
||||||
|
query: {
|
||||||
...attributeValidation,
|
...attributeValidation,
|
||||||
...sequelizeOperators,
|
...sequelizeOperators,
|
||||||
}),
|
},
|
||||||
get(methodConfig, 'validate.query')
|
},
|
||||||
);
|
});
|
||||||
|
|
||||||
methodConfig = set(methodConfig, 'validate.query', query);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasInclude) {
|
if (hasInclude) {
|
||||||
const query = concatToJoiObject(joi.object()
|
defaultsDeep(methodConfig, {
|
||||||
.keys({
|
validate: {
|
||||||
|
query: {
|
||||||
...associationValidation,
|
...associationValidation,
|
||||||
}),
|
},
|
||||||
get(methodConfig, 'validate.query')
|
},
|
||||||
);
|
});
|
||||||
|
|
||||||
methodConfig = set(methodConfig, 'validate.query', query);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasPayload) {
|
if (hasPayload) {
|
||||||
const payload = concatToJoiObject(joi.object()
|
defaultsDeep(methodConfig, {
|
||||||
.keys({
|
validate: {
|
||||||
|
payload: {
|
||||||
...attributeValidation,
|
...attributeValidation,
|
||||||
}),
|
},
|
||||||
get(methodConfig, 'validate.payload')
|
},
|
||||||
);
|
});
|
||||||
|
|
||||||
methodConfig = set(methodConfig, 'validate.payload', payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasScopeParams) {
|
|
||||||
const params = concatToJoiObject(joi.object()
|
|
||||||
.keys({
|
|
||||||
scope: joi.string().valid(...scopes),
|
|
||||||
}),
|
|
||||||
get(methodConfig, 'validate.params')
|
|
||||||
);
|
|
||||||
|
|
||||||
methodConfig = set(methodConfig, 'validate.params', params);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasIdParams) {
|
|
||||||
const params = concatToJoiObject(joi.object()
|
|
||||||
.keys({
|
|
||||||
id: joi.any(),
|
|
||||||
}),
|
|
||||||
get(methodConfig, 'validate.params')
|
|
||||||
);
|
|
||||||
|
|
||||||
methodConfig = set(methodConfig, 'validate.params', params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return methodConfig;
|
return methodConfig;
|
||||||
|
@ -5,22 +5,16 @@ import
|
|||||||
whereMethods,
|
whereMethods,
|
||||||
includeMethods,
|
includeMethods,
|
||||||
payloadMethods,
|
payloadMethods,
|
||||||
scopeParamsMethods,
|
|
||||||
idParamsMethods,
|
|
||||||
sequelizeOperators,
|
sequelizeOperators,
|
||||||
} from './get-config-for-method.js';
|
} from './get-config-for-method.js';
|
||||||
|
|
||||||
test.beforeEach((t) => {
|
test.beforeEach((t) => {
|
||||||
t.context.models = ['MyModel'];
|
|
||||||
|
|
||||||
t.context.scopes = ['aScope'];
|
|
||||||
|
|
||||||
t.context.attributeValidation = {
|
t.context.attributeValidation = {
|
||||||
myKey: joi.any(),
|
myKey: joi.any(),
|
||||||
};
|
};
|
||||||
|
|
||||||
t.context.associationValidation = {
|
t.context.associationValidation = {
|
||||||
include: joi.array().items(joi.string().valid(t.context.models)),
|
include: ['MyModel'],
|
||||||
};
|
};
|
||||||
|
|
||||||
t.context.config = {
|
t.context.config = {
|
||||||
@ -28,10 +22,11 @@ test.beforeEach((t) => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
test('validate.query seqeulizeOperators', (t) => {
|
test('get-config-for-method validate.query seqeulizeOperators', (t) => {
|
||||||
whereMethods.forEach((method) => {
|
whereMethods.forEach((method) => {
|
||||||
const configForMethod = getConfigForMethod({ method });
|
const configForMethod = getConfigForMethod({ method });
|
||||||
const { query } = configForMethod.validate;
|
const { query } = configForMethod.validate;
|
||||||
|
const configForMethodValidateQueryKeys = Object.keys(query);
|
||||||
|
|
||||||
t.truthy(
|
t.truthy(
|
||||||
query,
|
query,
|
||||||
@ -39,20 +34,15 @@ test('validate.query seqeulizeOperators', (t) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
Object.keys(sequelizeOperators).forEach((operator) => {
|
Object.keys(sequelizeOperators).forEach((operator) => {
|
||||||
t.ifError(
|
|
||||||
query.validate({ [operator]: true }).error
|
|
||||||
, `applies sequelize operator "${operator}" in validate.where for ${method}`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
t.truthy(
|
t.truthy(
|
||||||
query.validate({ notAThing: true }).error
|
configForMethodValidateQueryKeys.includes(operator),
|
||||||
, 'errors on a non-valid key'
|
`applies sequelize operator "${operator}" in validate.where for ${method}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test('validate.query attributeValidation', (t) => {
|
test('get-config-for-method validate.query attributeValidation', (t) => {
|
||||||
const { attributeValidation } = t.context;
|
const { attributeValidation } = t.context;
|
||||||
|
|
||||||
whereMethods.forEach((method) => {
|
whereMethods.forEach((method) => {
|
||||||
@ -60,96 +50,16 @@ test('validate.query attributeValidation', (t) => {
|
|||||||
const { query } = configForMethod.validate;
|
const { query } = configForMethod.validate;
|
||||||
|
|
||||||
Object.keys(attributeValidation).forEach((key) => {
|
Object.keys(attributeValidation).forEach((key) => {
|
||||||
t.ifError(
|
t.truthy(
|
||||||
query.validate({ [key]: true }).error
|
query[key]
|
||||||
, `applies attributeValidation (${key}) to validate.query`
|
, `applies attributeValidation (${key}) to validate.query`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
t.truthy(
|
|
||||||
query.validate({ notAThing: true }).error
|
|
||||||
, 'errors on a non-valid key'
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('query attributeValidation w/ config as plain object', (t) => {
|
test('get-config-for-method validate.query associationValidation', (t) => {
|
||||||
const { attributeValidation } = t.context;
|
const { attributeValidation, associationValidation } = t.context;
|
||||||
const config = {
|
|
||||||
validate: {
|
|
||||||
query: {
|
|
||||||
aKey: joi.boolean(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
whereMethods.forEach((method) => {
|
|
||||||
const configForMethod = getConfigForMethod({
|
|
||||||
method,
|
|
||||||
attributeValidation,
|
|
||||||
config,
|
|
||||||
});
|
|
||||||
const { query } = configForMethod.validate;
|
|
||||||
|
|
||||||
const keys = [
|
|
||||||
...Object.keys(attributeValidation),
|
|
||||||
...Object.keys(config.validate.query),
|
|
||||||
];
|
|
||||||
|
|
||||||
keys.forEach((key) => {
|
|
||||||
t.ifError(
|
|
||||||
query.validate({ [key]: true }).error
|
|
||||||
, `applies ${key} to validate.query`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
t.truthy(
|
|
||||||
query.validate({ notAThing: true }).error
|
|
||||||
, 'errors on a non-valid key'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('query attributeValidation w/ config as joi object', (t) => {
|
|
||||||
const { attributeValidation } = t.context;
|
|
||||||
const queryKeys = {
|
|
||||||
aKey: joi.boolean(),
|
|
||||||
};
|
|
||||||
const config = {
|
|
||||||
validate: {
|
|
||||||
query: joi.object().keys(queryKeys),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
whereMethods.forEach((method) => {
|
|
||||||
const configForMethod = getConfigForMethod({
|
|
||||||
method,
|
|
||||||
attributeValidation,
|
|
||||||
config,
|
|
||||||
});
|
|
||||||
const { query } = configForMethod.validate;
|
|
||||||
|
|
||||||
const keys = [
|
|
||||||
...Object.keys(attributeValidation),
|
|
||||||
...Object.keys(queryKeys),
|
|
||||||
];
|
|
||||||
|
|
||||||
keys.forEach((key) => {
|
|
||||||
t.ifError(
|
|
||||||
query.validate({ [key]: true }).error
|
|
||||||
, `applies ${key} to validate.query`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
t.truthy(
|
|
||||||
query.validate({ notAThing: true }).error
|
|
||||||
, 'errors on a non-valid key'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('validate.query associationValidation', (t) => {
|
|
||||||
const { attributeValidation, associationValidation, models } = t.context;
|
|
||||||
|
|
||||||
includeMethods.forEach((method) => {
|
includeMethods.forEach((method) => {
|
||||||
const configForMethod = getConfigForMethod({
|
const configForMethod = getConfigForMethod({
|
||||||
@ -160,106 +70,22 @@ test('validate.query associationValidation', (t) => {
|
|||||||
const { query } = configForMethod.validate;
|
const { query } = configForMethod.validate;
|
||||||
|
|
||||||
Object.keys(attributeValidation).forEach((key) => {
|
Object.keys(attributeValidation).forEach((key) => {
|
||||||
t.ifError(
|
t.truthy(
|
||||||
query.validate({ [key]: true }).error
|
query[key]
|
||||||
, `applies attributeValidation (${key}) to validate.query when include should be applied`
|
, `applies attributeValidation (${key}) to validate.query when include should be applied`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.keys(associationValidation).forEach((key) => {
|
Object.keys(associationValidation).forEach((key) => {
|
||||||
t.ifError(
|
t.truthy(
|
||||||
query.validate({ [key]: models }).error
|
query[key]
|
||||||
, `applies associationValidation (${key}) to validate.query when include should be applied`
|
, `applies associationValidation (${key}) to validate.query when include should be applied`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
t.truthy(
|
|
||||||
query.validate({ notAThing: true }).error
|
|
||||||
, 'errors on a non-valid key'
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('query associationValidation w/ config as plain object', (t) => {
|
test('get-config-for-method validate.payload associationValidation', (t) => {
|
||||||
const { associationValidation, models } = t.context;
|
|
||||||
const config = {
|
|
||||||
validate: {
|
|
||||||
query: {
|
|
||||||
aKey: joi.boolean(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
includeMethods.forEach((method) => {
|
|
||||||
const configForMethod = getConfigForMethod({
|
|
||||||
method,
|
|
||||||
associationValidation,
|
|
||||||
config,
|
|
||||||
});
|
|
||||||
const { query } = configForMethod.validate;
|
|
||||||
|
|
||||||
Object.keys(associationValidation).forEach((key) => {
|
|
||||||
t.ifError(
|
|
||||||
query.validate({ [key]: models }).error
|
|
||||||
, `applies ${key} to validate.query`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.keys(config.validate.query).forEach((key) => {
|
|
||||||
t.ifError(
|
|
||||||
query.validate({ [key]: true }).error
|
|
||||||
, `applies ${key} to validate.query`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
t.truthy(
|
|
||||||
query.validate({ notAThing: true }).error
|
|
||||||
, 'errors on a non-valid key'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('query associationValidation w/ config as joi object', (t) => {
|
|
||||||
const { associationValidation, models } = t.context;
|
|
||||||
const queryKeys = {
|
|
||||||
aKey: joi.boolean(),
|
|
||||||
};
|
|
||||||
const config = {
|
|
||||||
validate: {
|
|
||||||
query: joi.object().keys(queryKeys),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
includeMethods.forEach((method) => {
|
|
||||||
const configForMethod = getConfigForMethod({
|
|
||||||
method,
|
|
||||||
associationValidation,
|
|
||||||
config,
|
|
||||||
});
|
|
||||||
const { query } = configForMethod.validate;
|
|
||||||
|
|
||||||
Object.keys(associationValidation).forEach((key) => {
|
|
||||||
t.ifError(
|
|
||||||
query.validate({ [key]: models }).error
|
|
||||||
, `applies ${key} to validate.query`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.keys(queryKeys).forEach((key) => {
|
|
||||||
t.ifError(
|
|
||||||
query.validate({ [key]: true }).error
|
|
||||||
, `applies ${key} to validate.query`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
t.truthy(
|
|
||||||
query.validate({ notAThing: true }).error
|
|
||||||
, 'errors on a non-valid key'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('validate.payload associationValidation', (t) => {
|
|
||||||
const { attributeValidation } = t.context;
|
const { attributeValidation } = t.context;
|
||||||
|
|
||||||
payloadMethods.forEach((method) => {
|
payloadMethods.forEach((method) => {
|
||||||
@ -267,213 +93,20 @@ test('validate.payload associationValidation', (t) => {
|
|||||||
const { payload } = configForMethod.validate;
|
const { payload } = configForMethod.validate;
|
||||||
|
|
||||||
Object.keys(attributeValidation).forEach((key) => {
|
Object.keys(attributeValidation).forEach((key) => {
|
||||||
t.ifError(
|
t.truthy(
|
||||||
payload.validate({ [key]: true }).error
|
payload[key]
|
||||||
, `applies attributeValidation (${key}) to validate.payload`
|
, `applies attributeValidation (${key}) to validate.payload`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
t.truthy(
|
|
||||||
payload.validate({ notAThing: true }).error
|
|
||||||
, 'errors on a non-valid key'
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('payload attributeValidation w/ config as plain object', (t) => {
|
test('get-config-for-method does not modify initial config on multiple passes', (t) => {
|
||||||
const { attributeValidation } = t.context;
|
|
||||||
const config = {
|
|
||||||
validate: {
|
|
||||||
payload: {
|
|
||||||
aKey: joi.boolean(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
payloadMethods.forEach((method) => {
|
|
||||||
const configForMethod = getConfigForMethod({
|
|
||||||
method,
|
|
||||||
attributeValidation,
|
|
||||||
config,
|
|
||||||
});
|
|
||||||
const { payload } = configForMethod.validate;
|
|
||||||
|
|
||||||
const keys = [
|
|
||||||
...Object.keys(attributeValidation),
|
|
||||||
...Object.keys(config.validate.payload),
|
|
||||||
];
|
|
||||||
|
|
||||||
keys.forEach((key) => {
|
|
||||||
t.ifError(
|
|
||||||
payload.validate({ [key]: true }).error
|
|
||||||
, `applies ${key} to validate.payload`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
t.truthy(
|
|
||||||
payload.validate({ notAThing: true }).error
|
|
||||||
, 'errors on a non-valid key'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('payload attributeValidation w/ config as joi object', (t) => {
|
|
||||||
const { attributeValidation } = t.context;
|
|
||||||
const payloadKeys = {
|
|
||||||
aKey: joi.boolean(),
|
|
||||||
};
|
|
||||||
const config = {
|
|
||||||
validate: {
|
|
||||||
payload: joi.object().keys(payloadKeys),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
payloadMethods.forEach((method) => {
|
|
||||||
const configForMethod = getConfigForMethod({
|
|
||||||
method,
|
|
||||||
attributeValidation,
|
|
||||||
config,
|
|
||||||
});
|
|
||||||
const { payload } = configForMethod.validate;
|
|
||||||
|
|
||||||
const keys = [
|
|
||||||
...Object.keys(attributeValidation),
|
|
||||||
...Object.keys(payloadKeys),
|
|
||||||
];
|
|
||||||
|
|
||||||
keys.forEach((key) => {
|
|
||||||
t.ifError(
|
|
||||||
payload.validate({ [key]: true }).error
|
|
||||||
, `applies ${key} to validate.payload`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
t.truthy(
|
|
||||||
payload.validate({ notAThing: true }).error
|
|
||||||
, 'errors on a non-valid key'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('validate.params scopeParamsMethods', (t) => {
|
|
||||||
const { scopes } = t.context;
|
|
||||||
|
|
||||||
scopeParamsMethods.forEach((method) => {
|
|
||||||
const configForMethod = getConfigForMethod({ method, scopes });
|
|
||||||
const { params } = configForMethod.validate;
|
|
||||||
|
|
||||||
scopes.forEach((key) => {
|
|
||||||
t.ifError(
|
|
||||||
params.validate({ scope: key }).error
|
|
||||||
, `applies "scope: ${key}" to validate.params`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
t.truthy(
|
|
||||||
params.validate({ scope: 'notAthing' }).error
|
|
||||||
, 'errors on a non-valid key'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('params scopeParamsMethods w/ config as plain object', (t) => {
|
|
||||||
const { scopes } = t.context;
|
|
||||||
const config = {
|
|
||||||
validate: {
|
|
||||||
params: {
|
|
||||||
aKey: joi.boolean(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
scopeParamsMethods.forEach((method) => {
|
|
||||||
const configForMethod = getConfigForMethod({
|
|
||||||
method,
|
|
||||||
scopes,
|
|
||||||
config,
|
|
||||||
});
|
|
||||||
const { params } = configForMethod.validate;
|
|
||||||
|
|
||||||
scopes.forEach((key) => {
|
|
||||||
t.ifError(
|
|
||||||
params.validate({ scope: key }).error
|
|
||||||
, `applies "scope: ${key}" to validate.params`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.keys(config.validate.params).forEach((key) => {
|
|
||||||
t.ifError(
|
|
||||||
params.validate({ [key]: true }).error
|
|
||||||
, `applies ${key} to validate.params`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
t.truthy(
|
|
||||||
params.validate({ notAThing: true }).error
|
|
||||||
, 'errors on a non-valid key'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('params scopeParamsMethods w/ config as joi object', (t) => {
|
|
||||||
const { scopes } = t.context;
|
|
||||||
const paramsKeys = {
|
|
||||||
aKey: joi.boolean(),
|
|
||||||
};
|
|
||||||
const config = {
|
|
||||||
validate: {
|
|
||||||
params: joi.object().keys(paramsKeys),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
scopeParamsMethods.forEach((method) => {
|
|
||||||
const configForMethod = getConfigForMethod({
|
|
||||||
method,
|
|
||||||
scopes,
|
|
||||||
config,
|
|
||||||
});
|
|
||||||
const { params } = configForMethod.validate;
|
|
||||||
|
|
||||||
scopes.forEach((key) => {
|
|
||||||
t.ifError(
|
|
||||||
params.validate({ scope: key }).error
|
|
||||||
, `applies "scope: ${key}" to validate.params`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.keys(paramsKeys).forEach((key) => {
|
|
||||||
t.ifError(
|
|
||||||
params.validate({ [key]: true }).error
|
|
||||||
, `applies ${key} to validate.params`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
t.truthy(
|
|
||||||
params.validate({ notAThing: true }).error
|
|
||||||
, 'errors on a non-valid key'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
test('validate.payload idParamsMethods', (t) => {
|
|
||||||
idParamsMethods.forEach((method) => {
|
|
||||||
const configForMethod = getConfigForMethod({ method });
|
|
||||||
const { params } = configForMethod.validate;
|
|
||||||
|
|
||||||
t.ifError(
|
|
||||||
params.validate({ id: 'aThing' }).error
|
|
||||||
, 'applies id to validate.params'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('does not modify initial config on multiple passes', (t) => {
|
|
||||||
const { config } = t.context;
|
const { config } = t.context;
|
||||||
const originalConfig = { ...config };
|
const originalConfig = { ...config };
|
||||||
|
|
||||||
whereMethods.forEach((method) => {
|
whereMethods.forEach((method) => {
|
||||||
getConfigForMethod({ method, ...t.context });
|
getConfigForMethod({ method, config });
|
||||||
});
|
});
|
||||||
|
|
||||||
t.deepEqual(
|
t.deepEqual(
|
||||||
|
Reference in New Issue
Block a user