Skip to content

Commit

Permalink
Added assert package and added basic asserts
Browse files Browse the repository at this point in the history
  • Loading branch information
halvardssm committed Oct 13, 2024
1 parent 800413b commit a87f4b0
Show file tree
Hide file tree
Showing 13 changed files with 302 additions and 0 deletions.
15 changes: 15 additions & 0 deletions assert/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# @stdext/assert

The assert package, contains validators and assertions

```ts
import { assertIsString, isString } from "@stdext/assert";

if (isString(someVar)) {
// Returns true if a value is a string
// someVar will typewise be a string from now on
}

assertIsString(someVar); // Throws if the value is not a string
// someVar will typewise be a string from now on
```
10 changes: 10 additions & 0 deletions assert/deno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"version": "0.0.1",
"name": "@stdext/assert",
"exports": {
".": "./mod.ts",
"./is_number": "./is_number.ts",
"./is_record": "./is_record.ts",
"./is_string": "./is_string.ts"
}
}
47 changes: 47 additions & 0 deletions assert/is_number.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { assert, assertFalse, AssertionError, assertThrows } from "@std/assert";
import { assertIsNumber, isNumber } from "./is_number.ts";

const VALID = [
0,
1,
1.123,
1_123_12_3,
-1,
-1_1234,
-1.123,
NaN,
];

const INVALID = [
"",
"asdf",
undefined,
null,
{},
[],
[""],
new Number(),
];

Deno.test("isNumber > can detect numbers", () => {
for (const v of VALID) {
assert(isNumber(v), `Value of '${v}' is not valid`);
}
for (const v of INVALID) {
assertFalse(isNumber(v), `Value of '${v}' is not invalid`);
}
});

Deno.test("assertIsNumber > can detect numbers", () => {
for (const v of VALID) {
assertIsNumber(v);
}
for (const v of INVALID) {
assertThrows(
() => assertIsNumber(v),
AssertionError,
undefined,
`Value of '${v}' did not throw`,
);
}
});
17 changes: 17 additions & 0 deletions assert/is_number.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { AssertionError } from "@std/assert";

/**
* Checks if a value is a number
*/
export function isNumber(value: unknown): value is number {
return typeof value === "number";
}

/**
* Asserts that a value is a number
*/
export function assertIsNumber(value: unknown): asserts value is number {
if (!isNumber(value)) {
throw new AssertionError(`Value is not a number, was '${value}'`);
}
}
47 changes: 47 additions & 0 deletions assert/is_numeric.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { assert, assertFalse, AssertionError, assertThrows } from "@std/assert";
import { assertIsNumeric, isNumeric } from "./is_numeric.ts";

const VALID = [
0,
1,
1.123,
1_123_12_3,
-1,
-1_1234,
-1.123,
];

const INVALID = [
NaN,
"",
"asdf",
undefined,
null,
{},
[],
[""],
new Number(),
];

Deno.test("isNumeric > can detect numerics", () => {
for (const v of VALID) {
assert(isNumeric(v), `Value of '${v}' is not valid`);
}
for (const v of INVALID) {
assertFalse(isNumeric(v), `Value of '${v}' is not invalid`);
}
});

Deno.test("assertIsNumeric > can detect numerics", () => {
for (const v of VALID) {
assertIsNumeric(v);
}
for (const v of INVALID) {
assertThrows(
() => assertIsNumeric(v),
AssertionError,
undefined,
`Value of '${v}' did not throw`,
);
}
});
18 changes: 18 additions & 0 deletions assert/is_numeric.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { AssertionError } from "@std/assert";
import { isNumber } from "./is_number.ts";

/**
* Checks if a value is a number and not NaN
*/
export function isNumeric(value: unknown): value is number {
return isNumber(value) && !Number.isNaN(value);
}

/**
* Asserts that a value is a number and not NaN
*/
export function assertIsNumeric(value: unknown): asserts value is number {
if (!isNumeric(value)) {
throw new AssertionError(`Value is not a numeric, was '${value}'`);
}
}
42 changes: 42 additions & 0 deletions assert/is_record.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { assert, assertFalse, AssertionError, assertThrows } from "@std/assert";
import { assertIsRecord, isRecord } from "./is_record.ts";

const VALID = [
{},
{ a: 1 },
{ 1: "a" },
];

const INVALID = [
{ [Symbol.dispose]: "" },
"",
1,
undefined,
null,
[],
[""],
new Map(),
];

Deno.test("isRecord > can detect records", () => {
for (const v of VALID) {
assert(isRecord(v), `Value of '${v}' is not valid`);
}
for (const v of INVALID) {
assertFalse(isRecord(v), `Value of '${v}' is not invalid`);
}
});

Deno.test("assertIsRecord > can detect records", () => {
for (const v of VALID) {
assertIsRecord(v);
}
for (const v of INVALID) {
assertThrows(
() => assertIsRecord(v),
AssertionError,
undefined,
`Value of '${v}' did not throw`,
);
}
});
36 changes: 36 additions & 0 deletions assert/is_record.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { AssertionError } from "@std/assert";
import { objectToStringEquals } from "./utils.ts";

/**
* Checks if a value is a Record<string, unknown>
*/
export function isRecord(value: unknown): value is Record<string, unknown> {
if (!objectToStringEquals("Object", value)) {
return false;
}

if (typeof value !== "object") {
return false;
}

if (Array.isArray(value)) {
return false;
}

if (Object.getOwnPropertySymbols(value).length > 0) {
return false;
}

return true;
}

/**
* Asserts that a value is a record
*/
export function assertIsRecord(
value: unknown,
): asserts value is Record<string, unknown> {
if (!isRecord(value)) {
throw new AssertionError(`Value is not a Record, was '${value}'`);
}
}
40 changes: 40 additions & 0 deletions assert/is_string.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { assert, assertFalse, AssertionError, assertThrows } from "@std/assert";
import { assertIsString, isString } from "./is_string.ts";

const VALID = [
"",
"asdf",
];

const INVALID = [
1,
undefined,
null,
{},
[],
[""],
new String(),
];

Deno.test("isString > can detect strings", () => {
for (const v of VALID) {
assert(isString(v), `Value of '${v}' is not valid`);
}
for (const v of INVALID) {
assertFalse(isString(v), `Value of '${v}' is not invalid`);
}
});

Deno.test("assertIsString > can detect strings", () => {
for (const v of VALID) {
assertIsString(v);
}
for (const v of INVALID) {
assertThrows(
() => assertIsString(v),
AssertionError,
undefined,
`Value of '${v}' did not throw`,
);
}
});
17 changes: 17 additions & 0 deletions assert/is_string.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { AssertionError } from "@std/assert";

/**
* Checks if a value is a string
*/
export function isString(value: unknown): value is string {
return typeof value === "string";
}

/**
* Asserts that a value is a string
*/
export function assertIsString(value: unknown): asserts value is string {
if (!isString(value)) {
throw new AssertionError(`Value is not a string, was '${value}'`);
}
}
4 changes: 4 additions & 0 deletions assert/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from "./is_number.ts";
export * from "./is_numeric.ts";
export * from "./is_record.ts";
export * from "./is_string.ts";
7 changes: 7 additions & 0 deletions assert/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* Compares the Object.prototype.toString of the value against the given name
*/
export function objectToStringEquals(name: string, value: unknown): boolean {
const objectTag = `[object ${name}]`;
return Object.prototype.toString.call(value) === objectTag;
}
2 changes: 2 additions & 0 deletions deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"@std/encoding": "jsr:@std/encoding@^1.0.1",
"@std/json": "jsr:@std/json@^1.0.0",
"@std/path": "jsr:@std/path@^1.0.2",
"@stdext/assert": "jsr:@stdext/assert",
"@stdext/crypto": "jsr:@stdext/crypto",
"@stdext/encoding": "jsr:@stdext/encoding",
"@stdext/http": "jsr:@stdext/http",
Expand All @@ -24,6 +25,7 @@
"format:check": "deno fmt --check && deno task --cwd crypto format:check"
},
"workspace": [
"./assert",
"./crypto",
"./encoding",
"./http",
Expand Down

0 comments on commit a87f4b0

Please sign in to comment.