n4s
Version:
typed schema validation version of enforce
146 lines (119 loc) • 4.87 kB
text/typescript
import { describe, expect, it } from 'vitest';
import { enforce } from '../../../n4s';
describe('pick', () => {
it('Should successfully validate the picked subset of a schema', () => {
const schema = {
name: enforce.isString(),
age: enforce.isNumber(),
email: enforce.isString(),
};
const pickedSchema = enforce.pick(schema, ['name', 'age']);
// Pick name and age, validating valid inputs
// @ts-expect-error - partial object, un-picked keys omitted
const result = pickedSchema.run({ name: 'John Doe', age: 30 });
expect(result.pass).toBe(true);
// Test failing condition in the picked keys
const invalidResult = pickedSchema.run({
name: 'John Doe',
// @ts-expect-error - intentionally passing string instead of number
age: 'thirty',
});
expect(invalidResult.pass).toBe(false);
});
it('Should handle string param for keysToPick', () => {
const schema = {
id: enforce.isNumber(),
name: enforce.isString(),
};
const pickedSchema = enforce.pick(schema, 'id');
// @ts-expect-error - partial object, un-picked keys omitted
const result = pickedSchema.run({ id: 1 });
expect(result.pass).toBe(true);
const invalidResult = pickedSchema.run({
// @ts-expect-error - intentionally passing string instead of number
id: 'one',
});
expect(invalidResult.pass).toBe(false);
});
it('Should not fail validation for missing un-picked keys', () => {
const schema = {
name: enforce.isString(),
age: enforce.isNumber(),
email: enforce.isString(),
};
// 'email' is in the schema but missing in the value.
// If we only pick 'name' and 'age', it should still pass.
const pickedSchema = enforce.pick(schema, ['name', 'age']);
// @ts-expect-error - partial object, un-picked keys omitted
const result = pickedSchema.run({ name: 'John Doe', age: 30 });
expect(result.pass).toBe(true);
});
it('Should validate schema even if the payload has extra unspecified keys', () => {
const schema = {
id: enforce.isNumber(),
};
// 'extra' is not in the schema, but pick validates via loose under the hood
const pickedSchema = enforce.pick(schema, ['id']);
// @ts-expect-error - extra keys not in schema
const result = pickedSchema.run({ id: 1, extra: 'data' });
expect(result.pass).toBe(true);
});
it('Should fail immediately and return false if the value is not an object', () => {
const schema = { name: enforce.isString() };
const pickedSchema = enforce.pick(schema, ['name']);
// @ts-expect-error - testing non-object value
expect(pickedSchema.run('string_value').pass).toBe(false);
// @ts-expect-error - testing non-object value
expect(pickedSchema.run(123).pass).toBe(false);
// @ts-expect-error - testing non-object value
expect(pickedSchema.run(null).pass).toBe(false);
});
it('Should protect against dangerous prototype keys', () => {
const schema = { admin: enforce.isBoolean() };
const pickedSchema = enforce.pick(schema, ['admin']);
const dangerousValue = JSON.parse('{"__proto__": {"admin": true}}');
const result = pickedSchema.run(dangerousValue);
expect(result.pass).toBe(false);
});
it('Should fail when schema is not an object', () => {
const schema = 'not_a_schema';
// @ts-expect-error - testing non-object schema
const pickedSchema = enforce.pick(schema, ['id']);
const result = pickedSchema.run({ id: 1 });
expect(result.pass).toBe(false);
});
it('Should work with empty pick list', () => {
const schema = { id: enforce.isNumber() };
const pickedSchema = enforce.pick(schema, []);
const result = pickedSchema.run({
// @ts-expect-error - intentionally passing string instead of number
id: 'invalid_type_but_not_checked',
});
expect(result.pass).toBe(true);
});
it('Should pass with valid picked fields and ignore invalid un-picked fields', () => {
const schema = {
name: enforce.isString(),
age: enforce.isNumber(),
email: enforce.isString(),
};
const pickedSchema = enforce.pick(schema, ['name', 'age']);
// Should pass since we dropped the invalid email constraint
const result = pickedSchema.run({
name: 'John',
age: 30,
// @ts-expect-error - intentionally passing number instead of string
email: 123,
});
expect(result.pass).toBe(true);
// Should fail because age breaks the explicitly picked constraint
const invalidResult = pickedSchema.run({
name: 'John',
// @ts-expect-error - intentionally passing string instead of number
age: 'thirty',
// @ts-expect-error - intentionally passing number instead of string
email: 123,
});
expect(invalidResult.pass).toBe(false);
});
});