diff --git a/src/assertions/index.ts b/src/assertions/index.ts index 01cf26a..a47f7bf 100644 --- a/src/assertions/index.ts +++ b/src/assertions/index.ts @@ -27,6 +27,8 @@ export * from "./options"; export * from "./or"; export * from "./or2"; export * from "./or3"; +export * from "./rangeLength"; +export * from "./rangeValue"; export * from "./regex"; export * from "./startsWith"; export * from "./string"; diff --git a/src/assertions/rangeLength/index.test-d.ts b/src/assertions/rangeLength/index.test-d.ts new file mode 100644 index 0000000..2f45204 --- /dev/null +++ b/src/assertions/rangeLength/index.test-d.ts @@ -0,0 +1,5 @@ +import type { Assertion } from "@the-minimal/types"; +import { assertType } from "vitest"; +import { rangeLength } from "."; + +assertType>(rangeLength(8, 16)); diff --git a/src/assertions/rangeLength/index.test.ts b/src/assertions/rangeLength/index.test.ts new file mode 100644 index 0000000..69fecef --- /dev/null +++ b/src/assertions/rangeLength/index.test.ts @@ -0,0 +1,20 @@ +import { rangeLength } from "@assertions/rangeLength"; +import { fc, test } from "@fast-check/vitest"; +import { expect } from "vitest"; + +const assertion = rangeLength(8, 16); + +test.prop([fc.string({ minLength: 8, maxLength: 16 })])( + "should not throw if length of value is in the range of min and max", + (value) => { + expect(() => assertion(value)).not.toThrow(); + }, +); + +test.prop([fc.string({ maxLength: 7 }), fc.string({ minLength: 17 })])( + "should not throw if length of value is not in the range of min and max", + (v1, v2) => { + expect(() => assertion(v1)).toThrow(); + expect(() => assertion(v2)).toThrow(); + }, +); diff --git a/src/assertions/rangeLength/index.ts b/src/assertions/rangeLength/index.ts new file mode 100644 index 0000000..ced7904 --- /dev/null +++ b/src/assertions/rangeLength/index.ts @@ -0,0 +1,23 @@ +import { error } from "@error"; +import type { Assertion } from "@the-minimal/types"; + +/** + * Checks if length of value is in the range of min and max. + * + * @param min - Minimal value. + * @param max - Maximal value. + * + * @example + * ```ts + * const passwordLength = rangeLength(8, 16); + * + * passwordLength("hello"); // Error: rangeLength + * passwordLength("aaaaaaaaaaaaaaaaaaaa"); // Error: rangeLength + * passwordLength("Test123456"); // passes + * ``` + */ +export const rangeLength = + (min: number, max: number): Assertion<{ length: number }> => + (v) => + ((v as any).length >= min && (v as any).length <= max) || + error("rangeLength", v, { min, max }); diff --git a/src/assertions/rangeValue/index.test-d.ts b/src/assertions/rangeValue/index.test-d.ts new file mode 100644 index 0000000..843c75c --- /dev/null +++ b/src/assertions/rangeValue/index.test-d.ts @@ -0,0 +1,5 @@ +import { rangeValue } from "@assertions/rangeValue"; +import type { Assertion } from "@the-minimal/types"; +import { assertType } from "vitest"; + +assertType>(rangeValue(0, 150)); diff --git a/src/assertions/rangeValue/index.test.ts b/src/assertions/rangeValue/index.test.ts new file mode 100644 index 0000000..6c3b4c8 --- /dev/null +++ b/src/assertions/rangeValue/index.test.ts @@ -0,0 +1,20 @@ +import { rangeValue } from "@assertions/rangeValue"; +import { fc, test } from "@fast-check/vitest"; +import { expect } from "vitest"; + +const assertion = rangeValue(0, 150); + +test.prop([fc.integer({ min: 0, max: 150 })])( + "should not throw if value is in the range of min and max", + (value) => { + expect(() => assertion(value)).not.toThrow(); + }, +); + +test.prop([fc.integer({ max: -1 }), fc.integer({ min: 151 })])( + "should not throw if value is not in the range of min and max", + (v1, v2) => { + expect(() => assertion(v1)).toThrow(); + expect(() => assertion(v2)).toThrow(); + }, +); diff --git a/src/assertions/rangeValue/index.ts b/src/assertions/rangeValue/index.ts new file mode 100644 index 0000000..ac7f04e --- /dev/null +++ b/src/assertions/rangeValue/index.ts @@ -0,0 +1,23 @@ +import { error } from "@error"; +import type { Assertion } from "@the-minimal/types"; + +/** + * Checks if value is in the range of min and max. + * + * @param min - Minimal value. + * @param max - Maximal value. + * + * @example + * ```ts + * const alive = rangeValue(0, 150); + * + * alive(-10); // Error: rangeValue + * alive(450); // Error: rangeValue + * alive(26); // passes + * ``` + */ +export const rangeValue = + <$Type>(min: $Type, max: $Type): Assertion<$Type> => + (v) => + ((v as any) >= min && (v as any) <= max) || + error("rangeValue", v, { min, max });