From 93bf438fcdaceb296780a0a2eab529bacdc9b22d Mon Sep 17 00:00:00 2001 From: Geoff Date: Mon, 29 Jul 2024 18:13:00 -0400 Subject: [PATCH] Simplify tests for basic structs --- test/fixtures/fixtures.test.ts | 25 +++++++++++++ test/fixtures/fixtures.ts | 40 +++++++++++++++++++++ test/structs/any.test.ts | 15 ++++++++ test/structs/boolean.test.ts | 41 ++++++++++++++++++++++ test/structs/function.test.ts | 41 ++++++++++++++++++++++ test/structs/integer.test.ts | 41 ++++++++++++++++++++++ test/structs/literal.test.ts | 37 +++++++++++++++++++ test/structs/number.test.ts | 41 ++++++++++++++++++++++ test/structs/string.test.ts | 41 ++++++++++++++++++++++ test/structs/unknown.test.ts | 14 ++++++++ test/validation/any/valid-number.ts | 7 ---- test/validation/any/valid-string.ts | 7 ---- test/validation/any/valid-undefined.ts | 7 ---- test/validation/boolean/invalid.ts | 15 -------- test/validation/boolean/valid.ts | 7 ---- test/validation/function/invalid.ts | 15 -------- test/validation/function/valid.ts | 7 ---- test/validation/integer/invalid-decimal.ts | 15 -------- test/validation/integer/invalid.ts | 15 -------- test/validation/integer/valid.ts | 7 ---- test/validation/literal/invalid.ts | 15 -------- test/validation/literal/valid.ts | 7 ---- test/validation/number/invalid.ts | 15 -------- test/validation/number/valid.ts | 7 ---- test/validation/string/invalid.ts | 15 -------- test/validation/string/valid.ts | 7 ---- test/validation/unknown/valid-number.ts | 7 ---- test/validation/unknown/valid-string.ts | 7 ---- test/validation/unknown/valid-undefined.ts | 7 ---- 29 files changed, 336 insertions(+), 189 deletions(-) create mode 100644 test/fixtures/fixtures.test.ts create mode 100644 test/fixtures/fixtures.ts create mode 100644 test/structs/any.test.ts create mode 100644 test/structs/boolean.test.ts create mode 100644 test/structs/function.test.ts create mode 100644 test/structs/integer.test.ts create mode 100644 test/structs/literal.test.ts create mode 100644 test/structs/number.test.ts create mode 100644 test/structs/string.test.ts create mode 100644 test/structs/unknown.test.ts delete mode 100644 test/validation/any/valid-number.ts delete mode 100644 test/validation/any/valid-string.ts delete mode 100644 test/validation/any/valid-undefined.ts delete mode 100644 test/validation/boolean/invalid.ts delete mode 100644 test/validation/boolean/valid.ts delete mode 100644 test/validation/function/invalid.ts delete mode 100644 test/validation/function/valid.ts delete mode 100644 test/validation/integer/invalid-decimal.ts delete mode 100644 test/validation/integer/invalid.ts delete mode 100644 test/validation/integer/valid.ts delete mode 100644 test/validation/literal/invalid.ts delete mode 100644 test/validation/literal/valid.ts delete mode 100644 test/validation/number/invalid.ts delete mode 100644 test/validation/number/valid.ts delete mode 100644 test/validation/string/invalid.ts delete mode 100644 test/validation/string/valid.ts delete mode 100644 test/validation/unknown/valid-number.ts delete mode 100644 test/validation/unknown/valid-string.ts delete mode 100644 test/validation/unknown/valid-undefined.ts diff --git a/test/fixtures/fixtures.test.ts b/test/fixtures/fixtures.test.ts new file mode 100644 index 00000000..75886f4c --- /dev/null +++ b/test/fixtures/fixtures.test.ts @@ -0,0 +1,25 @@ +import { expect, test } from 'vitest' +import { data, fixtures } from './fixtures' + +test('Test that picking fixtures works as expected', () => { + const expected = [...data.integers(), ...data.strings(), ...data.functions()] + + const actual = fixtures.pick(['integers', 'strings', 'functions']) + + expect(JSON.stringify(actual)).toStrictEqual(JSON.stringify(expected)) +}) + +test('Test that omitting fixtures works as expected', () => { + const expected = [ + ...data.booleans(), + ...data.functions(), + ...data.nulls(), + ...data.undefineds(), + ...data.nan(), + ...data.floats(), + ] + + const actual = fixtures.omit(['integers', 'strings']) + + expect(JSON.stringify(actual)).toStrictEqual(JSON.stringify(expected)) +}) diff --git a/test/fixtures/fixtures.ts b/test/fixtures/fixtures.ts new file mode 100644 index 00000000..0d6b3b6b --- /dev/null +++ b/test/fixtures/fixtures.ts @@ -0,0 +1,40 @@ +import { flatMap, omit, pick, values } from 'lodash' + +type AllFixtures = { + booleans: () => unknown[] + functions: () => unknown[] + nulls: () => unknown[] + strings: () => unknown[] + undefineds: () => unknown[] + nan: () => unknown[] + floats: () => unknown[] + integers: () => unknown[] +} + +export const data: AllFixtures = { + booleans: () => [true, false], + functions: () => [ + () => {}, + (a: number, b: number) => a + b, + function namedFunction() {}, + ], + nulls: () => [null], + strings: () => ['Hello', '', '123', 'Special characters: !@#$%^&*()'], + undefineds: () => [undefined], + nan: () => [NaN], + floats: () => [3.14159], + integers: () => [3, -17, 0, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER], +} + +export const fixtures = { + all: (): unknown[] => flatMap(values(data), (value) => value()), + + pick: (keys: (keyof AllFixtures)[]): unknown[] => + flatMap(values(pick(data, keys)), (value) => value()), + + omit: (keys: (keyof AllFixtures)[]): unknown[] => { + const arrays: (() => unknown[])[] = values(omit(data, keys)) + + return flatMap(arrays, (value) => value()) + }, +} diff --git a/test/structs/any.test.ts b/test/structs/any.test.ts new file mode 100644 index 00000000..ea474e21 --- /dev/null +++ b/test/structs/any.test.ts @@ -0,0 +1,15 @@ +import { expect, test } from 'vitest' +import { fixtures } from '../fixtures/fixtures' +import { any } from '../../src' + +test('Everything is considered valid and returned as anything', () => { + const cases = fixtures.all() + + for (const c of cases) { + const [error, result] = any().validate(c) + + expect(error).toBeUndefined() + expect(result).toBe(c) + expect(result).toBeTypeOf(typeof c) + } +}) diff --git a/test/structs/boolean.test.ts b/test/structs/boolean.test.ts new file mode 100644 index 00000000..646dd0f1 --- /dev/null +++ b/test/structs/boolean.test.ts @@ -0,0 +1,41 @@ +import { expect, test } from 'vitest' +import { boolean, StructError } from '../../src' +import { print } from '../../src/utils' +import { fixtures } from '../fixtures/fixtures' + +test('Booleans are considered valid and returned as a boolean', () => { + const cases = fixtures.pick(['booleans']) + + for (const bool of cases) { + const [error, result] = boolean().validate(bool) + + expect(error).toBeUndefined() + expect(result).toBe(bool) + expect(result).toBeTypeOf('boolean') + } +}) + +test('Non booleans are considered invalid and returned with Error', () => { + const cases = fixtures.omit(['booleans']) + + for (const invalidBool of cases) { + const [error, result] = boolean().validate(invalidBool) + + expect(result).toBeUndefined() + + expect(error).not.toBeUndefined() + expect(error).toBeInstanceOf(StructError) + expect(error?.failures()).toStrictEqual([ + { + branch: [invalidBool], + explanation: undefined, + key: undefined, + message: `Expected a value of type \`boolean\`, but received: \`${print(invalidBool)}\``, + path: [], + refinement: undefined, + type: 'boolean', + value: invalidBool, + }, + ]) + } +}) diff --git a/test/structs/function.test.ts b/test/structs/function.test.ts new file mode 100644 index 00000000..90391b09 --- /dev/null +++ b/test/structs/function.test.ts @@ -0,0 +1,41 @@ +import { expect, test } from 'vitest' +import { func, StructError } from '../../src' +import { print } from '../../src/utils' +import { fixtures } from '../fixtures/fixtures' + +test('Functions are considered valid and returned as functions', () => { + const cases = fixtures.pick(['functions']) + + for (const f of cases) { + const [error, result] = func().validate(f) + + expect(error).toBeUndefined() + expect(result).toBe(f) + expect(f).toBeTypeOf('function') + } +}) + +test('Non functions are considered invalid and returned with Error', () => { + const cases = fixtures.omit(['functions']) + + for (const invalidFunc of cases) { + const [error, result] = func().validate(invalidFunc) + + expect(result).toBeUndefined() + + expect(error).not.toBeUndefined() + expect(error).toBeInstanceOf(StructError) + expect(error?.failures()).toStrictEqual([ + { + branch: [invalidFunc], + explanation: undefined, + key: undefined, + message: `Expected a function, but received: ${print(invalidFunc)}`, + path: [], + refinement: undefined, + type: 'func', + value: invalidFunc, + }, + ]) + } +}) diff --git a/test/structs/integer.test.ts b/test/structs/integer.test.ts new file mode 100644 index 00000000..151961fa --- /dev/null +++ b/test/structs/integer.test.ts @@ -0,0 +1,41 @@ +import { expect, test } from 'vitest' +import { integer, StructError } from '../../src' +import { print } from '../../src/utils' +import { fixtures } from '../fixtures/fixtures' + +test('Integers are considered valid and returned as a number', () => { + const cases = fixtures.pick(['integers']) + + for (const num of cases) { + const [error, result] = integer().validate(num) + + expect(error).toBeUndefined() + expect(result).toBe(num) + expect(result).toBeTypeOf('number') + } +}) + +test('Non integers are considered invalid and returned with Error', () => { + const cases = fixtures.omit(['integers']) + + for (const invalidNum of cases) { + const [error, result] = integer().validate(invalidNum) + + expect(result).toBeUndefined() + + expect(error).not.toBeUndefined() + expect(error).toBeInstanceOf(StructError) + expect(error?.failures()).toStrictEqual([ + { + branch: [invalidNum], + explanation: undefined, + key: undefined, + message: `Expected an integer, but received: ${print(invalidNum)}`, + path: [], + refinement: undefined, + type: 'integer', + value: invalidNum, + }, + ]) + } +}) diff --git a/test/structs/literal.test.ts b/test/structs/literal.test.ts new file mode 100644 index 00000000..6bcdc14e --- /dev/null +++ b/test/structs/literal.test.ts @@ -0,0 +1,37 @@ +import { expect, test } from 'vitest' +import { literal, StructError } from '../../src' +import { print } from '../../src/utils' +import { fixtures } from '../fixtures/fixtures' + +test('Literal is only considered valid and returned', () => { + const [error, result] = literal(42).validate(42) + + expect(error).toBeUndefined() + expect(result).toBe(42) + expect(result).toBeTypeOf('number') +}) + +test('Non integers are considered invalid and returned with Error', () => { + const cases = fixtures.all() + + for (const invalidLiteral of cases) { + const [error, result] = literal(42).validate(invalidLiteral) + + expect(result).toBeUndefined() + + expect(error).not.toBeUndefined() + expect(error).toBeInstanceOf(StructError) + expect(error?.failures()).toStrictEqual([ + { + branch: [invalidLiteral], + explanation: undefined, + key: undefined, + message: `Expected the literal \`42\`, but received: ${print(invalidLiteral)}`, + path: [], + refinement: undefined, + type: 'literal', + value: invalidLiteral, + }, + ]) + } +}) diff --git a/test/structs/number.test.ts b/test/structs/number.test.ts new file mode 100644 index 00000000..4d96ee3b --- /dev/null +++ b/test/structs/number.test.ts @@ -0,0 +1,41 @@ +import { expect, test } from 'vitest' +import { number, StructError } from '../../src' +import { print } from '../../src/utils' +import { fixtures } from '../fixtures/fixtures' + +test('Numbers are considered valid and returned as a number', () => { + const cases = fixtures.pick(['floats', 'integers']) + + for (const num of cases) { + const [error, result] = number().validate(num) + + expect(error).toBeUndefined() + expect(result).toBe(num) + expect(result).toBeTypeOf('number') + } +}) + +test('Non numbers are considered invalid and returned with Error', () => { + const cases = fixtures.omit(['floats', 'integers']) + + for (const invalidNum of cases) { + const [error, result] = number().validate(invalidNum) + + expect(result).toBeUndefined() + + expect(error).not.toBeUndefined() + expect(error).toBeInstanceOf(StructError) + expect(error?.failures()).toStrictEqual([ + { + branch: [invalidNum], + explanation: undefined, + key: undefined, + message: `Expected a number, but received: ${print(invalidNum)}`, + path: [], + refinement: undefined, + type: 'number', + value: invalidNum, + }, + ]) + } +}) diff --git a/test/structs/string.test.ts b/test/structs/string.test.ts new file mode 100644 index 00000000..93920d04 --- /dev/null +++ b/test/structs/string.test.ts @@ -0,0 +1,41 @@ +import { expect, test } from 'vitest' +import { string, StructError } from '../../src' +import { print } from '../../src/utils' +import { fixtures } from '../fixtures/fixtures' + +test('Strings are considered valid and returned as a string', () => { + const cases = fixtures.pick(['strings']) + + for (const strings of cases) { + const [error, result] = string().validate(strings) + + expect(error).toBeUndefined() + expect(result).toBe(strings) + expect(result).toBeTypeOf('string') + } +}) + +test('Non strings are considered invalid and returned with Error', () => { + const cases = fixtures.omit(['strings']) + + for (const invalidStrings of cases) { + const [error, result] = string().validate(invalidStrings) + + expect(result).toBeUndefined() + + expect(error).not.toBeUndefined() + expect(error).toBeInstanceOf(StructError) + expect(error?.failures()).toStrictEqual([ + { + branch: [invalidStrings], + explanation: undefined, + key: undefined, + message: `Expected a string, but received: ${print(invalidStrings)}`, + path: [], + refinement: undefined, + type: 'string', + value: invalidStrings, + }, + ]) + } +}) diff --git a/test/structs/unknown.test.ts b/test/structs/unknown.test.ts new file mode 100644 index 00000000..ee57dd5d --- /dev/null +++ b/test/structs/unknown.test.ts @@ -0,0 +1,14 @@ +import { expect, test } from 'vitest' +import { fixtures } from '../fixtures/fixtures' +import { unknown } from '../../src' + +test('Everything is considered valid and returned as unknown', () => { + const cases = fixtures.all() + + for (const c of cases) { + const [error, result] = unknown().validate(c) + + expect(error).toBeUndefined() + expect(result).toBe(c) + } +}) diff --git a/test/validation/any/valid-number.ts b/test/validation/any/valid-number.ts deleted file mode 100644 index 70af230d..00000000 --- a/test/validation/any/valid-number.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { any } from '../../../src' - -export const Struct = any() - -export const data = 1 - -export const output = 1 diff --git a/test/validation/any/valid-string.ts b/test/validation/any/valid-string.ts deleted file mode 100644 index 3ee3159d..00000000 --- a/test/validation/any/valid-string.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { any } from '../../../src' - -export const Struct = any() - -export const data = 'valid' - -export const output = 'valid' diff --git a/test/validation/any/valid-undefined.ts b/test/validation/any/valid-undefined.ts deleted file mode 100644 index d22b8108..00000000 --- a/test/validation/any/valid-undefined.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { any } from '../../../src' - -export const Struct = any() - -export const data = undefined - -export const output = undefined diff --git a/test/validation/boolean/invalid.ts b/test/validation/boolean/invalid.ts deleted file mode 100644 index 01b05be6..00000000 --- a/test/validation/boolean/invalid.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { boolean } from '../../../src' - -export const Struct = boolean() - -export const data = 'invalid' - -export const failures = [ - { - value: 'invalid', - type: 'boolean', - refinement: undefined, - path: [], - branch: [data], - }, -] diff --git a/test/validation/boolean/valid.ts b/test/validation/boolean/valid.ts deleted file mode 100644 index 86d8c122..00000000 --- a/test/validation/boolean/valid.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { boolean } from '../../../src' - -export const Struct = boolean() - -export const data = true - -export const output = true diff --git a/test/validation/function/invalid.ts b/test/validation/function/invalid.ts deleted file mode 100644 index dbc7bdd8..00000000 --- a/test/validation/function/invalid.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { func } from '../../../src' - -export const Struct = func() - -export const data = false - -export const failures = [ - { - value: false, - type: 'func', - refinement: undefined, - path: [], - branch: [data], - }, -] diff --git a/test/validation/function/valid.ts b/test/validation/function/valid.ts deleted file mode 100644 index a9318bbe..00000000 --- a/test/validation/function/valid.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { func } from '../../../src' - -export const Struct = func() - -export const data = function () {} - -export const output = data diff --git a/test/validation/integer/invalid-decimal.ts b/test/validation/integer/invalid-decimal.ts deleted file mode 100644 index f39e1185..00000000 --- a/test/validation/integer/invalid-decimal.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { integer } from '../../../src' - -export const Struct = integer() - -export const data = 3.14 - -export const failures = [ - { - value: 3.14, - type: 'integer', - refinement: undefined, - path: [], - branch: [data], - }, -] diff --git a/test/validation/integer/invalid.ts b/test/validation/integer/invalid.ts deleted file mode 100644 index d3732b18..00000000 --- a/test/validation/integer/invalid.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { integer } from '../../../src' - -export const Struct = integer() - -export const data = 'invalid' - -export const failures = [ - { - value: 'invalid', - type: 'integer', - refinement: undefined, - path: [], - branch: [data], - }, -] diff --git a/test/validation/integer/valid.ts b/test/validation/integer/valid.ts deleted file mode 100644 index 34673bf2..00000000 --- a/test/validation/integer/valid.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { integer } from '../../../src' - -export const Struct = integer() - -export const data = 42 - -export const output = 42 diff --git a/test/validation/literal/invalid.ts b/test/validation/literal/invalid.ts deleted file mode 100644 index f7473a3e..00000000 --- a/test/validation/literal/invalid.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { literal } from '../../../src' - -export const Struct = literal(42) - -export const data = false - -export const failures = [ - { - value: false, - type: 'literal', - refinement: undefined, - path: [], - branch: [data], - }, -] diff --git a/test/validation/literal/valid.ts b/test/validation/literal/valid.ts deleted file mode 100644 index 70ea8fb4..00000000 --- a/test/validation/literal/valid.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { literal } from '../../../src' - -export const Struct = literal(42) - -export const data = 42 - -export const output = 42 diff --git a/test/validation/number/invalid.ts b/test/validation/number/invalid.ts deleted file mode 100644 index 140420e7..00000000 --- a/test/validation/number/invalid.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { number } from '../../../src' - -export const Struct = number() - -export const data = 'invalid' - -export const failures = [ - { - value: 'invalid', - type: 'number', - refinement: undefined, - path: [], - branch: [data], - }, -] diff --git a/test/validation/number/valid.ts b/test/validation/number/valid.ts deleted file mode 100644 index 8ea8b9a2..00000000 --- a/test/validation/number/valid.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { number } from '../../../src' - -export const Struct = number() - -export const data = 42 - -export const output = 42 diff --git a/test/validation/string/invalid.ts b/test/validation/string/invalid.ts deleted file mode 100644 index 16634387..00000000 --- a/test/validation/string/invalid.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { string } from '../../../src' - -export const Struct = string() - -export const data = false - -export const failures = [ - { - value: false, - type: 'string', - refinement: undefined, - path: [], - branch: [data], - }, -] diff --git a/test/validation/string/valid.ts b/test/validation/string/valid.ts deleted file mode 100644 index afc40fac..00000000 --- a/test/validation/string/valid.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { string } from '../../../src' - -export const Struct = string() - -export const data = 'valid' - -export const output = 'valid' diff --git a/test/validation/unknown/valid-number.ts b/test/validation/unknown/valid-number.ts deleted file mode 100644 index 9238214a..00000000 --- a/test/validation/unknown/valid-number.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { unknown } from '../../../src' - -export const Struct = unknown() - -export const data = 1 - -export const output = 1 diff --git a/test/validation/unknown/valid-string.ts b/test/validation/unknown/valid-string.ts deleted file mode 100644 index 7e82b944..00000000 --- a/test/validation/unknown/valid-string.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { unknown } from '../../../src' - -export const Struct = unknown() - -export const data = 'valid' - -export const output = 'valid' diff --git a/test/validation/unknown/valid-undefined.ts b/test/validation/unknown/valid-undefined.ts deleted file mode 100644 index d90f1439..00000000 --- a/test/validation/unknown/valid-undefined.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { unknown } from '../../../src' - -export const Struct = unknown() - -export const data = undefined - -export const output = undefined