hapi-sequelize-crud/src/get-config-for-method.test.js
Joey Baker c59943a717 Fix (validation) use joi's concat
It turns out defaultsDeep doesn't ever correctly combine Joi objects.
So, the only option is to use Joi's concat method to combine Joi
schemas. This complicates `getConfigForMethod`, but simplifies actual
route creation.

I ran into this because I'm setting up [lout](https://github.com/hapijs/lout)
on a server, and it requires properly formatted Joi schemas. This leads
me to believe there was something already wrong and Lout just exposed
the problem.
2016-09-08 13:20:50 -07:00

485 lines
11 KiB
JavaScript

import test from 'ava';
import joi from 'joi';
import
getConfigForMethod, {
whereMethods,
includeMethods,
payloadMethods,
scopeParamsMethods,
idParamsMethods,
sequelizeOperators,
} from './get-config-for-method.js';
test.beforeEach((t) => {
t.context.models = ['MyModel'];
t.context.scopes = ['aScope'];
t.context.attributeValidation = {
myKey: joi.any(),
};
t.context.associationValidation = {
include: joi.array().items(joi.string().valid(t.context.models)),
};
t.context.config = {
cors: {},
};
});
test('validate.query seqeulizeOperators', (t) => {
whereMethods.forEach((method) => {
const configForMethod = getConfigForMethod({ method });
const { query } = configForMethod.validate;
t.truthy(
query,
`applies query validation for ${method}`
);
Object.keys(sequelizeOperators).forEach((operator) => {
t.ifError(
query.validate({ [operator]: true }).error
, `applies sequelize operator "${operator}" in validate.where for ${method}`
);
});
t.truthy(
query.validate({ notAThing: true }).error
, 'errors on a non-valid key'
);
});
});
test('validate.query attributeValidation', (t) => {
const { attributeValidation } = t.context;
whereMethods.forEach((method) => {
const configForMethod = getConfigForMethod({ method, attributeValidation });
const { query } = configForMethod.validate;
Object.keys(attributeValidation).forEach((key) => {
t.ifError(
query.validate({ [key]: true }).error
, `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) => {
const { attributeValidation } = 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) => {
const configForMethod = getConfigForMethod({
method,
attributeValidation,
associationValidation,
});
const { query } = configForMethod.validate;
Object.keys(attributeValidation).forEach((key) => {
t.ifError(
query.validate({ [key]: true }).error
, `applies attributeValidation (${key}) to validate.query when include should be applied`
);
});
Object.keys(associationValidation).forEach((key) => {
t.ifError(
query.validate({ [key]: models }).error
, `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) => {
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;
payloadMethods.forEach((method) => {
const configForMethod = getConfigForMethod({ method, attributeValidation });
const { payload } = configForMethod.validate;
Object.keys(attributeValidation).forEach((key) => {
t.ifError(
payload.validate({ [key]: true }).error
, `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) => {
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 originalConfig = { ...config };
whereMethods.forEach((method) => {
getConfigForMethod({ method, ...t.context });
});
t.deepEqual(
config
, originalConfig
, 'does not modify the original config object'
);
});