Skip to content

Commit 259657b

Browse files
authored
Merge pull request #1 from RobDWaller/0.1.0
0.1.0
2 parents aad2c3d + 4e5a430 commit 259657b

7 files changed

Lines changed: 311 additions & 3 deletions

File tree

README.md

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,113 @@
1+
[![Actions Status](https://github.com/robdwaller/explicitly/workflows/ci/badge.svg)](https://github.com/robdwaller/explicitly/actions)
2+
13
# Explicitly
24

3-
Extends the code Deno assertion library with additional assertions so developers can write more explicit Unit Tests if they choose to.
5+
This library extends the [Deno assertions module](https://github.com/denoland/deno/blob/master/std/testing/asserts.ts) with additional assertions so developers can write more explicit unit tests if they choose to. It works with [Deno Test Tools](https://deno.land/manual/testing) in the same way the built in assertions do.
6+
7+
The principle behind this library is unit tests should focus small units of business logic. Assertions should therefore focus on the assertion of basic types in an explicit manner. This library provides assertions which fulfill this requirement and all the assertions are simple and specific which makes the intent of a unit test clearer.
8+
9+
For more generalised equality checks, better suited to integration or functional tests, please use the built in [Deno assertions module](https://github.com/denoland/deno/blob/master/std/testing/asserts.ts).
10+
11+
## Installation
12+
13+
Before you use this library make sure you have read and understood how to set up [Deno Tests](https://deno.land/manual/testing).
14+
15+
To install this library and make use of the assertions in your test suite simply add the following import to the test modules which require it.
16+
17+
```js
18+
import {
19+
assertTrue,
20+
assertFalse,
21+
assertSame,
22+
assertGreater,
23+
assertGreaterOrEqual,
24+
assertLess,
25+
assertLessOrEqual,
26+
assertInstanceOf,
27+
assertTypeOf,
28+
} from "https://raw.githubusercontent.com/RobDWaller/explicitly/0.1.0/mod.ts";
29+
```
30+
31+
## Basic Usage
32+
33+
This assertion library comes with nine basic assertions methods:
34+
35+
- `assertTrue(actual: unknown): void`
36+
- `assertFalse(actual: unknown): void`
37+
- `assertSame(actual: unknown, expected: unknown): void`
38+
- `assertGreater(actual: unknown, expected: unknown): void`
39+
- `assertGreaterOrEqual(actual: unknown, expected: unknown): void`
40+
- `assertLess(actual: unknown, expected: unknown): void`
41+
- `assertLessOrEqual(actual: unknown, expected: unknown): void`
42+
- `assertInstanceOf(actual: unknown, expected: any): void`
43+
- `assertTypeOf(actual: unknown, expected: string): void`
44+
45+
Each of these assertions aims to test a single thing. This means unit tests are explicit and clearer to read.
46+
47+
### Assert True Example
48+
49+
A basic example of when you may wish to assert true.
50+
51+
```js
52+
Deno.test("Assert True Example", () => {
53+
function isOlderThanFive(age: number): boolean {
54+
return age >= 5;
55+
}
56+
57+
const childAge: number = 6;
58+
59+
const result: boolean = isOlderThanFive(childAge);
60+
61+
assertTrue(result);
62+
});
63+
```
64+
65+
### Assert Instance Of Example
66+
67+
A more advanced example of when you may wish to assert an instance of. Usually when there is a polymorphic relationship between objects.
68+
69+
```js
70+
Deno.test("Assert Instance Of Example", () => {
71+
interface Person {
72+
name: string;
73+
age: number;
74+
location: string;
75+
}
76+
77+
class Adult implements Person {
78+
name: string;
79+
age: number;
80+
location: string;
81+
82+
constructor(name: string, age: number, location: string) {
83+
this.name = name;
84+
this.age = age;
85+
this.location = location;
86+
}
87+
}
88+
89+
class Child implements Person {
90+
name: string;
91+
age: number;
92+
location: string;
93+
94+
constructor(name: string, age: number, location: string) {
95+
this.name = name;
96+
this.age = age;
97+
this.location = location;
98+
}
99+
}
100+
101+
function createPerson(name: string, age: number, location: string): Person {
102+
if (age < 18) {
103+
return new Child(name, age, location);
104+
}
105+
106+
return new Adult(name, age, location);
107+
}
108+
109+
const jenny = createPerson("Jenny Brown", 12, "US");
110+
111+
assertInstanceOf(jenny, Child);
112+
});
113+
```

mod.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import {
44
greaterOrEqual,
55
less,
66
lessOrEqual,
7+
instanceOf,
8+
typeOf,
79
} from "./src/equality.ts";
810
import {
911
AssertionError,
@@ -43,3 +45,11 @@ export function assertLess(actual: unknown, expected: unknown): void {
4345
export function assertLessOrEqual(actual: unknown, expected: unknown): void {
4446
handleError(lessOrEqual(actual, expected));
4547
}
48+
49+
export function assertInstanceOf(actual: unknown, expected: any): void {
50+
handleError(instanceOf(actual, expected));
51+
}
52+
53+
export function assertTypeOf(actual: unknown, expected: string): void {
54+
handleError(typeOf(actual, expected));
55+
}

src/equality.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Result, ok, err } from "https://deno.land/x/resulty/mod.ts";
2-
import { error } from "./message.ts";
2+
import { error, errorSimple } from "./message.ts";
33

44
export function equals(actual: unknown, expected: unknown): Result<string> {
55
if (actual === expected) {
@@ -44,3 +44,25 @@ export function lessOrEqual(actual: any, expected: any): Result<string> {
4444
error(actual, expected, "is not less than or equal to expected value"),
4545
);
4646
}
47+
48+
export function instanceOf(
49+
actual: unknown,
50+
expected: any,
51+
): Result<string> {
52+
if (actual instanceof expected) {
53+
return ok(`${actual} is instance of ${expected}`);
54+
}
55+
56+
return err(errorSimple(actual, expected, "is not an instance of"));
57+
}
58+
59+
export function typeOf(
60+
actual: unknown,
61+
expected: string,
62+
): Result<string> {
63+
if (typeof actual === expected) {
64+
return ok(`${actual} is type of ${expected}`);
65+
}
66+
67+
return err(errorSimple(actual, expected, "is not a type of"));
68+
}

src/message.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,17 @@ export function error(
2828
green(`"${getValueOrName(expected)}" type of ${typeof expected}.`),
2929
);
3030
}
31+
32+
export function errorSimple(
33+
actual: unknown,
34+
expected: unknown,
35+
text: string,
36+
): string {
37+
let message: string = red(
38+
`"${getValueOrName(actual)}"`,
39+
);
40+
message = message.concat(` ${text} `);
41+
return message.concat(
42+
green(`"${getValueOrName(expected)}".`),
43+
);
44+
}

tests/equality.test.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import {
66
greaterOrEqual,
77
less,
88
lessOrEqual,
9+
instanceOf,
10+
typeOf,
911
} from "../src/equality.ts";
1012

1113
Deno.test("Equals Boolean", () => {
@@ -67,3 +69,40 @@ Deno.test("Less or Equal Fail", () => {
6769

6870
assertTrue(result.isError());
6971
});
72+
73+
Deno.test("Instance Of", () => {
74+
class Foo {}
75+
76+
const foo = new Foo();
77+
78+
const result: Result<string> = instanceOf(foo, Foo);
79+
80+
assertTrue(result.isOk());
81+
});
82+
83+
Deno.test("Instance Of Fail", () => {
84+
class Foo {}
85+
class Bar {}
86+
87+
const foo = new Foo();
88+
89+
const result: Result<string> = instanceOf(foo, Bar);
90+
91+
assertTrue(result.isError());
92+
});
93+
94+
Deno.test("Type Of", () => {
95+
const hello = "World";
96+
97+
const result: Result<string> = typeOf(hello, "string");
98+
99+
assertTrue(result.isOk());
100+
});
101+
102+
Deno.test("Type Of Fail", () => {
103+
const hello = "World";
104+
105+
const result: Result<string> = typeOf(hello, "boolean");
106+
107+
assertTrue(result.isError());
108+
});

tests/message.test.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
33
green,
44
} from "https://deno.land/std/fmt/colors.ts";
55
import { assertSame } from "../mod.ts";
6-
import { error } from "../src/message.ts";
6+
import { error, errorSimple } from "../src/message.ts";
77

88
Deno.test("Create Message", () => {
99
const actual = error(true, true, "equals");
@@ -37,3 +37,16 @@ Deno.test("Create Message With Functions", () => {
3737

3838
assertSame(actual, expected);
3939
});
40+
41+
Deno.test("Create Simple Message", () => {
42+
class Foo {}
43+
class Bar {}
44+
45+
const foo = new Foo();
46+
47+
const actual = errorSimple(foo, Bar, "is not instance of");
48+
const expected = red(`"Foo"`) + " is not instance of " +
49+
green(`"Bar".`);
50+
51+
assertSame(actual, expected);
52+
});

tests/mod.test.ts

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import {
1414
assertGreaterOrEqual,
1515
assertLess,
1616
assertLessOrEqual,
17+
assertInstanceOf,
18+
assertTypeOf,
1719
} from "../mod.ts";
1820

1921
Deno.test("Assert True", () => {
@@ -170,3 +172,101 @@ Deno.test("Assert Greater or Equal Fail", () => {
170172
message,
171173
);
172174
});
175+
176+
Deno.test("Assert Instance Of", () => {
177+
class Foo {}
178+
const foo = new Foo();
179+
assertInstanceOf(foo, Foo);
180+
});
181+
182+
Deno.test("Assert Instance Of Fail", () => {
183+
const message = red(`"Foo"`) +
184+
" is not an instance of " +
185+
green(`"Bar".`);
186+
187+
class Foo {}
188+
class Bar {}
189+
const foo = new Foo();
190+
191+
assertThrows(
192+
(): void => {
193+
assertInstanceOf(foo, Bar);
194+
},
195+
AssertionError,
196+
message,
197+
);
198+
});
199+
200+
Deno.test("Assert Type Of", () => {
201+
assertTypeOf(2, "number");
202+
});
203+
204+
Deno.test("Assert Type Of Fail", () => {
205+
const message = red(`"3"`) +
206+
" is not a type of " +
207+
green(`"string".`);
208+
209+
assertThrows(
210+
(): void => {
211+
assertTypeOf(3, "string");
212+
},
213+
AssertionError,
214+
message,
215+
);
216+
});
217+
218+
Deno.test("Assert True Example", () => {
219+
function isOlderThanFive(age: number): boolean {
220+
return age >= 5;
221+
}
222+
223+
const childAge: number = 6;
224+
225+
const result: boolean = isOlderThanFive(childAge);
226+
227+
assertTrue(result);
228+
});
229+
230+
Deno.test("Assert Instance Of Example", () => {
231+
interface Person {
232+
name: string;
233+
age: number;
234+
location: string;
235+
}
236+
237+
class Adult implements Person {
238+
name: string;
239+
age: number;
240+
location: string;
241+
242+
constructor(name: string, age: number, location: string) {
243+
this.name = name;
244+
this.age = age;
245+
this.location = location;
246+
}
247+
}
248+
249+
class Child implements Person {
250+
name: string;
251+
age: number;
252+
location: string;
253+
254+
constructor(name: string, age: number, location: string) {
255+
this.name = name;
256+
this.age = age;
257+
this.location = location;
258+
}
259+
}
260+
261+
function createPerson(name: string, age: number, location: string): Person {
262+
if (age < 18) {
263+
return new Child(name, age, location);
264+
}
265+
266+
return new Adult(name, age, location);
267+
}
268+
269+
const jenny = createPerson("Jenny Brown", 12, "US");
270+
271+
assertInstanceOf(jenny, Child);
272+
});

0 commit comments

Comments
 (0)