Skip to content

Commit

Permalink
fix: check all locations if in is not specified.
Browse files Browse the repository at this point in the history
  • Loading branch information
nikli2009 committed Aug 16, 2021
1 parent 690cd63 commit 989f0bb
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/context.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ describe('#getData()', () => {

context.addFieldInstances(data);

expect(context.getData()).toEqual([data[0]]);
expect(context.getData()).toEqual(data);
});

it('does not filter out second undefined when it contains a wildcard', () => {
Expand Down
4 changes: 2 additions & 2 deletions src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ export class Context {
const locations = _.uniqBy(instances, 'location');

// #331 - When multiple locations are involved, all of them must pass the validation.
// If none of the locations contain the field, we at least include one for error reporting.
// checkSchema: If `in` option is not specified, try to check all locations by default.
// #458, #531 - Wildcards are an exception though: they may yield 0..* instances with different
// paths, so we may want to skip this filtering.
if (instances.length > 1 && locations.length > 1 && !group.includes('*')) {
const withValue = instances.filter(instance => instance.value !== undefined);
return withValue.length ? withValue : [instances[0]];
return withValue.length ? withValue : instances;
}

return instances;
Expand Down
92 changes: 90 additions & 2 deletions src/middlewares/schema.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,49 @@ describe('on each field', () => {
const { context } = await chain.run({ params: { foo: '' } });
expect(context.errors).toHaveLength(1);
});

it('use default config when specified', async () => {
const chain = checkSchema({
undef: {
default: {
options: 10,
},
},
})[0];

const req = { query: { undef: undefined }, body: {}, params: {}, headers: {}, cookies: {} };
const { context } = await chain.run(req);

expect(context.getData().every(instance => instance.value === 10)).toBe(true);
expect(req.query.undef).toBe(10);
expect((req as any).body.undef).toBe(10);
expect((req as any).headers.undef).toBe(10);
expect((req as any).params.undef).toBe(10);
expect((req as any).cookies.undef).toBe(10);
});
});

describe('when ParamSchema location not specified', () => {
it('should validate locations only in which the field can be found', async () => {
const schema = checkSchema({
foo: {
isInt: true,
toInt: true,
},
});
const { context } = await schema[0].run({
query: { foo: 'foo' },
params: { foo: 'true' },
});

expect(context.errors).toHaveLength(2);
});
});
describe('on schema that contains fields with bail methods', () => {
it('stops validation chain with only one error', async () => {
it('stops validation chain with only one error with specified location', async () => {
const schema = checkSchema({
foo: {
in: ['params'],
exists: {
bail: true,
},
Expand All @@ -200,7 +237,57 @@ describe('on schema that contains fields with bail methods', () => {
},
});

const { context } = await schema[0].run({ params: {} });
const { context } = await schema[0].run({ query: {} });
expect(context.errors).toHaveLength(1);
});

it('stops validation chain if any validation fails with "exist" validator', async () => {
const allLocations = ['body', 'cookies', 'headers', 'params', 'query'];
const schema = checkSchema({
foo: {
exists: {
bail: true,
errorMessage: 'exists checking failed',
},
isLength: {
options: {
min: 5,
},
},
},
});

const { context } = await schema[0].run({ query: {} });
// when location is not specified, checking each location one by one,
// if the expected field does not show up at all in any location, then there will be 5 errors.
// finally bails.
expect(context.errors).toHaveLength(allLocations.length);
// context.errors should not contain any error from next validator -> isLength.
expect(context.errors.every(err => err.msg === 'exists checking failed')).toBe(true);
});

it('stops validation chain if any validation fails with sanitizer', async () => {
const schema = checkSchema({
foo: {
toInt: true,
isInt: {
bail: true,
},
isLength: {
options: {
min: 5,
},
},
},
});

const { context } = await schema[0].run({ query: { foo: 'true' } });
const {
errors: [firstError],
} = context;

// simply make sure it's sanitizer-result-caused error.
expect(firstError.value).toBe(NaN);
expect(context.errors).toHaveLength(1);
});

Expand All @@ -225,6 +312,7 @@ describe('on schema that contains fields with bail methods', () => {
it('bails with message', async () => {
const schema = checkSchema({
foo: {
in: ['params'],
exists: {
bail: true,
errorMessage: 'Value not exists',
Expand Down
17 changes: 17 additions & 0 deletions src/middlewares/validation-chain-builders.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,23 @@ describe('buildCheckFunction()', () => {
value: 'asd',
});
});

describe('when at least 1 locations specified', () => {
// for #1010
it('should apply default value to each specified location if default option is not empty', async () => {
const custom = buildCheckFunction(['cookies', 'headers']);
const chain = custom('bar').default(10);

await chain.run(req);

expect(req.cookies).toHaveProperty('bar', 10);
expect(req.headers).toHaveProperty('bar', 10);

expect(req.body).not.toHaveProperty('bar');
expect(req.params).not.toHaveProperty('bar');
expect(req.query).not.toHaveProperty('bar');
});
});
});

describe('check()', () => {
Expand Down

0 comments on commit 989f0bb

Please sign in to comment.