diff --git a/src/schema/field/arrays/allowed.ts b/src/schema/field/arrays/allowed.ts index df706e2..edd450e 100644 --- a/src/schema/field/arrays/allowed.ts +++ b/src/schema/field/arrays/allowed.ts @@ -26,8 +26,7 @@ import {type SchemaFieldType} from '../type'; /** - * Determine if array support is enabled based on all supported types for a single - * schema field. + * Determine if field supports array values based on field types. * @param items Field types to check. * * @category Schema – Field diff --git a/src/transform/verified.ts b/src/transform/verified.ts index ebeae6e..2e5fb00 100644 --- a/src/transform/verified.ts +++ b/src/transform/verified.ts @@ -27,7 +27,7 @@ import {Fate} from '@toreda/fate'; import {Log} from '@toreda/log'; import {schemaError} from '../schema/error'; import {type VerifiedMap} from '../verified/map'; -import {Transformed} from '../transformed'; +import {type Transformed} from '../transformed'; import {transformVerifiedField} from './verified/field'; /** diff --git a/src/transformed/field.ts b/src/transformed/field.ts index 8d0fa8e..c235d26 100644 --- a/src/transformed/field.ts +++ b/src/transformed/field.ts @@ -24,6 +24,8 @@ */ /** + * Type returned by functions that transform verified field data. Fields may contain + * scalar values, nulls, subfields, and arrays containing the former. * @param id * @param data * @param base diff --git a/tests/empty.spec.ts b/tests/empty.spec.ts new file mode 100644 index 0000000..413fe5a --- /dev/null +++ b/tests/empty.spec.ts @@ -0,0 +1,67 @@ +import {empty} from '../src/empty'; +const EMPTY_ARRAY: string[] = []; + +describe('empty', () => { + it(`should return false when value is undefined`, () => { + expect(empty(undefined)).toBe(false); + }); + + it(`should return false when value is null`, () => { + expect(empty(null)).toBe(false); + }); + + it(`should return false when value is a non-empty array`, () => { + expect(empty([11, 'aa'])).toBe(false); + }); + + it(`should return true when value is an empty array`, () => { + expect(empty(EMPTY_ARRAY)).toBe(true); + }); + + it(`should return true when value is an empty object`, () => { + expect(empty({})).toBe(true); + }); + + it(`should return false when value is a non-empty string`, () => { + expect(empty('aaaaaa')).toBe(false); + }); + + it(`should return false when value is a non-empty string`, () => { + expect(empty('aaaaaa')).toBe(false); + }); + + it(`should return true when value is a space-padded empty string`, () => { + let value = ' '; + + for (let i = 0; i < 5; i++) { + expect(empty(value)).toBe(true); + value += ' '; + } + }); + + it(`should return true when value is an non-empty object`, () => { + expect( + empty({ + one: 'aaaaa' + }) + ).toBe(false); + }); + + it(`should return false when value is a boolean (true)`, () => { + expect(empty(true)).toBe(false); + }); + + it(`should return false when value is a boolean (true)`, () => { + expect(empty(false)).toBe(false); + }); + + it(`should return false when value is a falsy number (0)`, () => { + expect(empty(0)).toBe(false); + }); + + it(`should return false when value is a truthy number`, () => { + expect(empty(1)).toBe(false); + expect(empty(10000)).toBe(false); + expect(empty(-1)).toBe(false); + }); +}); diff --git a/tests/schema/field/arrays/allowed.spec.ts b/tests/schema/field/arrays/allowed.spec.ts new file mode 100644 index 0000000..502bce5 --- /dev/null +++ b/tests/schema/field/arrays/allowed.spec.ts @@ -0,0 +1,123 @@ +import {SchemaFieldType} from '../../../../src'; +import {schemaFieldArraysAllowed} from '../../../../src/schema/field/arrays/allowed'; +import {schemaFieldTypes} from '../../../../src/schema/field/types'; + +const EMPTY_STRING = ''; +const EMPTY_OBJECT = {}; +const EMPTY_STR_ARRAY: string[] = []; + +const NON_ARRAY_TYPES: SchemaFieldType[] = [ + 'bigint', + 'BigInt', + 'boolean', + 'datetime', + 'dbl', + 'double', + 'float', + 'int', + 'iterable', + 'json', + 'null', + 'number', + 'serialized', + 'string', + 'time', + 'uint', + 'undefined', + 'url' +]; + +const ARRAY_TYPES: SchemaFieldType[] = [ + 'bigint[]', + 'BigInt[]', + 'boolean[]', + 'datetime[]', + 'datetime[]', + 'dbl[]', + 'double[]', + 'float[]', + 'int[]', + 'iterable[]', + 'json[]', + 'null[]', + 'number[]', + 'serialized[]', + 'string[]', + 'time[]', + 'undefined[]', + 'url[]' +]; + +describe('schemaFieldArraysAllowed', () => { + it(`should return false when items arg is an empty string`, () => { + expect(schemaFieldArraysAllowed(EMPTY_STRING as any)).toBe(false); + }); + + it(`should return false when items arg is a string`, () => { + expect(schemaFieldArraysAllowed('f087145081-998132' as any)).toBe(false); + }); + + it(`should return false when items arg is an empty array`, () => { + expect(schemaFieldArraysAllowed(EMPTY_STR_ARRAY as any)).toBe(false); + }); + + it(`should return false when items arg is an empty object`, () => { + expect(schemaFieldArraysAllowed(EMPTY_OBJECT as any)).toBe(false); + }); + + it(`should return false for all built-in non-array types'`, () => { + expect(schemaFieldArraysAllowed(NON_ARRAY_TYPES)).toBe(false); + }); + + it(`should return true when one item is an array type among non-array types`, () => { + const input: SchemaFieldType[] = [...NON_ARRAY_TYPES, 'number[]']; + expect(schemaFieldArraysAllowed(input)).toBe(true); + }); + + it(`should return true when items array has one array type`, () => { + expect(schemaFieldArraysAllowed(['BigInt[]'])).toBe(true); + }); + + for (const fieldType of NON_ARRAY_TYPES) { + it(`should return false when items arg is a single non-array type '${fieldType}'`, () => { + expect(schemaFieldArraysAllowed([fieldType])).toBe(false); + }); + } + + for (const fieldType of ARRAY_TYPES) { + it(`should return true when items array has one array type '${fieldType}'`, () => { + expect(schemaFieldArraysAllowed([fieldType])).toBe(true); + }); + } + + it(`should return true when the last item is an array type and all other elements are skipped due to being non-strings`, () => { + expect( + schemaFieldArraysAllowed([ + undefined, + null, + 1000, + {}, + [], + '___', + EMPTY_STRING, + 'BigInt[]' + ] as any) + ).toBe(true); + }); + + it(`should return true when items arg contains a non-builtin type ending in '[]'`, () => { + expect( + schemaFieldArraysAllowed([ + null, + undefined, + 10, + 100, + 91910, + '---', + 'string', + 'undefined', + 'customtype[]' + ] as any) + ).toBe(true); + }); +}); diff --git a/tests/transform/verified.spec.ts b/tests/transform/verified.spec.ts new file mode 100644 index 0000000..efd632d --- /dev/null +++ b/tests/transform/verified.spec.ts @@ -0,0 +1,46 @@ +import {Primitive} from '@toreda/types'; +import {transformVerified} from '../../src/transform/verified'; +import {schemaError} from '../../src'; +import {Levels, Log} from '@toreda/log'; + +describe('transformVerified', () => { + let verifiedMap: Map; + let base: Log; + + beforeAll(() => { + verifiedMap = new Map(); + base = new Log({ + consoleEnabled: true, + globalLevel: Levels.ALL, + groupsStartEnabled: true + }); + }); + + beforeEach(() => { + verifiedMap.clear(); + }); + + describe('Base parameters', () => { + it(`should fail with code when base arg is undefined`, async () => { + const result = await transformVerified(verifiedMap, undefined as any); + expect(result.ok()).toBe(false); + + expect(result.errorCode()).toBe(schemaError('missing_argument', 'transformVerified', 'base')); + }); + + it(`should fail with code when base arg is null`, async () => { + const result = await transformVerified(verifiedMap, null as any); + expect(result.ok()).toBe(false); + + expect(result.errorCode()).toBe(schemaError('missing_argument', 'transformVerified', 'base')); + }); + + it(`should succeed when input is an empty map`, async () => { + expect(verifiedMap.size).toBe(0); + + const result = await transformVerified(verifiedMap, base); + expect(result.ok()).toBe(true); + expect(result.data).toStrictEqual({}); + }); + }); +});