UNPKG

validata

Version:

Type safe data validation and sanitization

325 lines 15.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const json_date_parser_1 = require("json-date-parser"); const date_1 = require("./date"); const number_1 = require("./number"); const object_1 = require("./object"); const string_1 = require("./string"); const test_helpers_1 = require("./test-helpers"); const types_1 = require("./types"); describe('isObject', () => { it('will fail non-object', () => { const fut = (0, object_1.isObject)(); (0, test_helpers_1.expectIssue)(fut, null, 'not-defined'); (0, test_helpers_1.expectIssue)(fut, undefined, 'not-defined'); (0, test_helpers_1.expectIssue)(fut, 0, 'incorrect-type'); (0, test_helpers_1.expectIssue)(fut, new Date(), 'incorrect-type'); (0, test_helpers_1.expectIssue)(fut, [], 'incorrect-type'); (0, test_helpers_1.expectIssue)(fut, 'test', 'incorrect-type'); }); it('will accept object', () => { const fut = (0, object_1.isObject)(); (0, test_helpers_1.expectSuccess)(fut, {}); (0, test_helpers_1.expectSuccess)(fut, { a: 47 }); }); it('will process children', () => { const fut = (0, object_1.isObject)({ a: (0, number_1.asNumber)({ coerceMin: 25 }), b: (0, string_1.asString)(), }); (0, test_helpers_1.expectValue)(fut, { a: 47, b: 'asd' }, { a: 47, b: 'asd' }); (0, test_helpers_1.expectValue)(fut, { a: '47', b: 12 }, { a: 47, b: '12' }); (0, test_helpers_1.expectValue)(fut, { a: '7', b: 12 }, { a: 25, b: '12' }); }); it('will process nested children', () => { const fut = (0, object_1.isObject)({ o: (0, object_1.isObject)({ a: (0, number_1.isNumber)(), b: (0, string_1.asString)(), }), s: (0, string_1.asString)(), }); (0, test_helpers_1.runTests)(fut, { input: { o: 47, s: 'asd' }, issues: [{ reason: 'incorrect-type', path: ['o'] }], }, { input: { o: {}, s: 'asd' }, issues: [{ reason: 'not-defined', path: ['o', 'a'] }], }, { input: { o: { a: 'hello', b: 'hello' }, s: 'asd' }, issues: [{ reason: 'incorrect-type', path: ['o', 'a'] }], }, { expect: { o: { a: 12, b: '12' }, s: 'asd' }, input: { o: { a: 12, b: 12 }, s: 'asd' }, }); }); it('will process children', () => { const fut = (0, object_1.isObject)({ a: (0, number_1.isNumber)({ min: 25 }), b: (0, string_1.isString)(), }); (0, test_helpers_1.expectValue)(fut, { a: 47, b: 'asd' }, { a: 47, b: 'asd' }); (0, test_helpers_1.expectIssue)(fut, { a: '47', b: 'asd' }, 'incorrect-type', ['a']); (0, test_helpers_1.expectIssue)(fut, { a: 47, b: 'asd', c: 234 }, 'unexpected-property', ['c']); (0, test_helpers_1.expectIssue)(fut, {}, 'not-defined', ['a']); (0, test_helpers_1.expectIssue)(fut, {}, 'not-defined', ['b']); }); it('will handle optional property', () => { const fut = (0, object_1.isObject)({ a: (0, number_1.isNumber)(), b: (0, string_1.maybeString)(), }); (0, test_helpers_1.expectIssue)(fut, {}, 'not-defined', ['a']); (0, test_helpers_1.expectIssue)(fut, { b: 'asd' }, 'not-defined', ['a']); { const result = (0, test_helpers_1.expectSuccess)(fut, { a: 42 }); expect(result.value).not.toHaveProperty('b'); } { const result = (0, test_helpers_1.expectSuccess)(fut, { a: 42, b: undefined }); expect(result.value).toHaveProperty('b'); expect(result.value.b).toEqual(undefined); } { const result = (0, test_helpers_1.expectSuccess)(fut, { a: 42, b: null }); expect(result.value).toHaveProperty('b'); expect(result.value.b).toEqual(undefined); } }); it('will error on unexpected properties', () => { const fut = (0, object_1.isObject)({ a: (0, number_1.isNumber)({ min: 25 }), b: (0, string_1.isString)(), }); (0, test_helpers_1.expectIssue)(fut, { a: 47, b: 'asd', c: 234 }, 'unexpected-property', ['c']); }); it('will strip unexpected properties', () => { const fut = (0, object_1.isObject)({ a: (0, number_1.isNumber)({ min: 25 }), b: (0, string_1.isString)(), }, { stripExtraProperties: true }); (0, test_helpers_1.expectValue)(fut, { a: 47, b: 'asd', c: 345, d: 'hello' }, { a: 47, b: 'asd' }); }); it('will ignore unexpected properties', () => { const fut = (0, object_1.isObject)({ a: (0, number_1.isNumber)({ min: 25 }), b: (0, string_1.isString)(), }, { ignoreExtraProperties: true }); (0, test_helpers_1.expectValue)(fut, { a: 47, b: 'asd', c: 345, d: 'hello' }, { a: 47, b: 'asd', c: 345, d: 'hello' }); }); it('will check with custom validator returning custom issues', () => { const fut = (0, object_1.isObject)({ a: (0, number_1.isNumber)({ min: 25 }), b: (0, string_1.isString)({ validator: (value, _options, path) => value === 'triggerCustom' ? [types_1.Issue.forPath(path !== null && path !== void 0 ? path : [], value, 'custom')] : true }), }); (0, test_helpers_1.expectIssue)(fut, { a: 47, b: 'triggerCustom' }, 'custom', ['b']); }); }); describe('maybeObject', () => { it('will coerce null and undefined', () => { const fut = (0, object_1.maybeObject)(); (0, test_helpers_1.expectValue)(fut, null, undefined); (0, test_helpers_1.expectValue)(fut, undefined, undefined); }); it('will fail non-object', () => { const fut = (0, object_1.maybeObject)(); (0, test_helpers_1.expectIssue)(fut, 0, 'incorrect-type'); (0, test_helpers_1.expectIssue)(fut, new Date(), 'incorrect-type'); (0, test_helpers_1.expectIssue)(fut, [], 'incorrect-type'); (0, test_helpers_1.expectIssue)(fut, 'test', 'incorrect-type'); }); it('will accept non-object if requested', () => { const fut = (0, object_1.maybeObject)({}, { incorrectTypeToUndefined: true }); (0, test_helpers_1.expectValue)(fut, 0, undefined); (0, test_helpers_1.expectValue)(fut, new Date(), undefined); (0, test_helpers_1.expectValue)(fut, [], undefined); (0, test_helpers_1.expectValue)(fut, 'test', undefined); }); it('will accept object', () => { const fut = (0, object_1.maybeObject)(); (0, test_helpers_1.expectSuccess)(fut, {}); (0, test_helpers_1.expectSuccess)(fut, { a: 47 }); }); }); describe('asObject', () => { it('will fail non-object', () => { const fut = (0, object_1.asObject)(); (0, test_helpers_1.expectIssue)(fut, null, 'not-defined'); (0, test_helpers_1.expectIssue)(fut, undefined, 'not-defined'); (0, test_helpers_1.expectIssue)(fut, 0, 'no-conversion'); (0, test_helpers_1.expectIssue)(fut, new Date(), 'no-conversion'); (0, test_helpers_1.expectIssue)(fut, [], 'no-conversion'); (0, test_helpers_1.expectIssue)(fut, 'test', 'no-conversion'); }); it('will use default', () => { const fut = (0, object_1.asObject)({ a: (0, number_1.asNumber)(), b: (0, string_1.asString)(), }, { default: { a: 47, b: 'default' } }); (0, test_helpers_1.expectValue)(fut, null, { a: 47, b: 'default' }); (0, test_helpers_1.expectValue)(fut, undefined, { a: 47, b: 'default' }); }); it('will accept object', () => { const fut = (0, object_1.asObject)(); (0, test_helpers_1.expectSuccess)(fut, {}); (0, test_helpers_1.expectSuccess)(fut, { a: 47 }); }); it('will process children', () => { const fut = (0, object_1.asObject)({ a: (0, number_1.asNumber)({ coerceMin: 25 }), b: (0, string_1.asString)(), }); (0, test_helpers_1.expectValue)(fut, { a: 47, b: 'asd' }, { a: 47, b: 'asd' }); (0, test_helpers_1.expectValue)(fut, { a: '47', b: 12 }, { a: 47, b: '12' }); (0, test_helpers_1.expectValue)(fut, { a: '7', b: 12 }, { a: 25, b: '12' }); }); it('will process nested children', () => { const fut = (0, object_1.asObject)({ o: (0, object_1.isObject)({ a: (0, number_1.isNumber)(), b: (0, string_1.asString)(), }), s: (0, string_1.asString)(), }); (0, test_helpers_1.runTests)(fut, { input: { o: 47, s: 'asd' }, issues: [{ reason: 'incorrect-type', path: ['o'] }], }, { input: { o: {}, s: 'asd' }, issues: [{ reason: 'not-defined', path: ['o', 'a'] }], }, { input: { o: { a: 'hello', b: 'hello' }, s: 'asd' }, issues: [{ reason: 'incorrect-type', path: ['o', 'a'] }], }, { expect: { o: { a: 12, b: '12' }, s: 'asd' }, input: { o: { a: 12, b: 12 }, s: 'asd' }, }); }); it('will process children', () => { const fut = (0, object_1.asObject)({ a: (0, number_1.isNumber)({ min: 25 }), b: (0, string_1.isString)(), }); (0, test_helpers_1.expectValue)(fut, { a: 47, b: 'asd' }, { a: 47, b: 'asd' }); (0, test_helpers_1.expectIssue)(fut, { a: '47', b: 'asd' }, 'incorrect-type', ['a']); (0, test_helpers_1.expectIssue)(fut, { a: 47, b: 'asd', c: 234 }, 'unexpected-property', ['c']); (0, test_helpers_1.expectIssue)(fut, {}, 'not-defined', ['a']); (0, test_helpers_1.expectIssue)(fut, {}, 'not-defined', ['b']); }); it('will error on unexpected properties', () => { const fut = (0, object_1.asObject)({ a: (0, number_1.isNumber)({ min: 25 }), b: (0, string_1.isString)(), }); (0, test_helpers_1.expectIssue)(fut, { a: 47, b: 'asd', c: 234 }, 'unexpected-property', ['c']); }); it('will strip unexpected properties', () => { const fut = (0, object_1.asObject)({ a: (0, number_1.isNumber)({ min: 25 }), b: (0, string_1.isString)(), }, { stripExtraProperties: true }); (0, test_helpers_1.expectValue)(fut, { a: 47, b: 'asd', c: 345, d: 'hello' }, { a: 47, b: 'asd' }); }); describe('string parsing', () => { const fut = (0, object_1.asObject)({ a: (0, number_1.isNumber)({ min: 25 }), b: (0, string_1.isString)(), }); it('will fail empty string', () => { (0, test_helpers_1.expectIssue)(fut, '', 'no-conversion'); }); it('will fail nonJSON string', () => { (0, test_helpers_1.expectIssue)(fut, 'testing', 'no-conversion'); }); it('will fail invalid JSON string', () => { (0, test_helpers_1.expectIssue)(fut, '{testing=12}', 'no-conversion'); (0, test_helpers_1.expectIssue)(fut, '{testing:12}', 'no-conversion'); }); it('will parse valid JSON string that matches requirements', () => { (0, test_helpers_1.expectValue)(fut, '{"a": 123, "b": "test"}', { a: 123, b: 'test' }); }); it('will parse valid JSON string that doesn\'t match requirements', () => { (0, test_helpers_1.expectIssue)(fut, '{}', 'not-defined', ['a']); (0, test_helpers_1.expectIssue)(fut, '{}', 'not-defined', ['b']); (0, test_helpers_1.expectIssue)(fut, '{"a": "123", "b": "test"}', 'incorrect-type', ['a']); }); }); }); describe('maybeAsObject', () => { it('will coerce null and undefined', () => { const fut = (0, object_1.maybeAsObject)(); (0, test_helpers_1.expectValue)(fut, null, undefined); (0, test_helpers_1.expectValue)(fut, undefined, undefined); }); it('will use default', () => { const fut = (0, object_1.maybeAsObject)({ a: (0, number_1.asNumber)(), b: (0, string_1.asString)(), }, { default: { a: 47, b: 'default' } }); (0, test_helpers_1.expectValue)(fut, null, { a: 47, b: 'default' }); (0, test_helpers_1.expectValue)(fut, undefined, { a: 47, b: 'default' }); }); it('will convert non-object to undefined', () => { const fut = (0, object_1.maybeAsObject)(); (0, test_helpers_1.expectValue)(fut, 0, undefined); (0, test_helpers_1.expectValue)(fut, new Date(), undefined); (0, test_helpers_1.expectValue)(fut, [], undefined); (0, test_helpers_1.expectValue)(fut, 'test', undefined); }); it('will fail invalid JSON string when parsing is strict', () => { const fut = (0, object_1.maybeAsObject)({}, { strictParsing: true }); (0, test_helpers_1.expectIssue)(fut, 0, 'no-conversion'); (0, test_helpers_1.expectIssue)(fut, 'test', 'no-conversion'); (0, test_helpers_1.expectIssue)(fut, '{testing=12}', 'no-conversion'); (0, test_helpers_1.expectIssue)(fut, '{testing:12}', 'no-conversion'); }); it('will accept non-object if requested', () => { const fut = (0, object_1.maybeAsObject)({}, { incorrectTypeToUndefined: true }); (0, test_helpers_1.expectValue)(fut, 0, undefined); (0, test_helpers_1.expectValue)(fut, new Date(), undefined); (0, test_helpers_1.expectValue)(fut, [], undefined); (0, test_helpers_1.expectValue)(fut, 'test', undefined); }); it('will accept object', () => { const fut = (0, object_1.maybeAsObject)(); (0, test_helpers_1.expectSuccess)(fut, {}); (0, test_helpers_1.expectSuccess)(fut, { a: 47 }); }); describe('string parsing', () => { const fut = (0, object_1.maybeAsObject)({ a: (0, number_1.isNumber)({ min: 25 }), b: (0, string_1.isString)(), }); it('will convert empty string to undefined', () => { (0, test_helpers_1.expectValue)(fut, '', undefined); }); it('will convert nonJSON string to undefined', () => { (0, test_helpers_1.expectValue)(fut, 'testing', undefined); }); it('will convert invalid JSON string to undefined', () => { (0, test_helpers_1.expectValue)(fut, '{testing=12}', undefined); (0, test_helpers_1.expectValue)(fut, '{testing:12}', undefined); }); it('will use custom converter', () => { const fut = (0, object_1.asObject)({ d: (0, date_1.isDate)() }, { converter: (value) => typeof value !== 'string' ? undefined : JSON.parse(value, json_date_parser_1.jsonDateParser) }); (0, test_helpers_1.expectIssue)(fut, '{"d":12}', 'incorrect-type', ['d']); const date = '2021-01-13T20:23:36.164Z'; const r = fut.process(`{"d":"${date}"}`); expect(r).toBeDefined(); if ((0, types_1.isIssue)(r)) { fail(`Unexpected issue: ${JSON.stringify(r)}`); } expect(r.value.d.constructor.name).toEqual('Date'); expect(r.value.d.getTime()).toEqual(new Date(date).getTime()); }); it('will parse valid JSON string that matches requirements', () => { (0, test_helpers_1.expectValue)(fut, '{"a": 123, "b": "test"}', { a: 123, b: 'test' }); }); it('will parse valid JSON string that doesn\'t match requirements', () => { (0, test_helpers_1.expectIssue)(fut, '{}', 'not-defined', ['a']); (0, test_helpers_1.expectIssue)(fut, '{}', 'not-defined', ['b']); (0, test_helpers_1.expectIssue)(fut, '{"a": "123", "b": "test"}', 'incorrect-type', ['a']); }); }); }); //# sourceMappingURL=object.test.js.map