Skip to content

Commit aee48fb

Browse files
committed
feat: add more tests
1 parent 44972f8 commit aee48fb

4 files changed

Lines changed: 155 additions & 37 deletions

File tree

src/try.test.ts

Lines changed: 0 additions & 36 deletions
This file was deleted.

tests/base.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { describe, expect, test } from "bun:test";
2+
import { Failure, Success, Try } from "@microlib/try";
3+
4+
describe("Basic functionality", () => {
5+
test("Can be instantiated", () => {
6+
const t = new Try(() => true);
7+
expect(t.ok).toBe(true);
8+
expect(Try.isTry(t)).toBe(true);
9+
expect(Try.unwrap(t)).toBe(true);
10+
});
11+
12+
test("Can be used as a function", () => {
13+
const t = Try(() => true);
14+
expect(t.ok).toBe(true);
15+
expect(Try.isTry(t)).toBe(true);
16+
expect(Try.unwrap(t)).toBe(true);
17+
});
18+
19+
test("Outcome Success, Try.success()", () => {
20+
const t = Try.success("pass");
21+
expect(t.ok).toBe(true);
22+
expect(Try.isOk(t)).toBe(true);
23+
expect(Try.isError(t)).toBe(false);
24+
expect(Try.isTry(t)).toBe(true);
25+
expect(t).toBeInstanceOf(Success);
26+
expect(Try.unwrap(t)).toBe("pass");
27+
});
28+
29+
test("Outcome Failure, Try.failure()", () => {
30+
const t = Try.failure("fail");
31+
expect(t.ok).toBe(false);
32+
expect(Try.isOk(t)).toBe(false);
33+
expect(Try.isError(t)).toBe(true);
34+
expect(Try.isTry(t)).toBe(true);
35+
expect(t).toBeInstanceOf(Failure);
36+
expect(() => Try.unwrap(t)).toThrowError("fail");
37+
});
38+
});

tests/promise.test.ts

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import { describe, expect, test } from "bun:test";
2+
import { Failure, Success, Try } from "@microlib/try";
3+
4+
describe("Try API Mimics Promise", () => {
5+
test("Try.success behaves like Promise.resolve", () => {
6+
const success = Try.success(42);
7+
expect(success.ok).toBe(true);
8+
expect(success).toBeInstanceOf(Success);
9+
expect(Try.unwrap(success)).toBe(42);
10+
});
11+
12+
test("Try.failure behaves like Promise.reject", () => {
13+
const error = new Error("Failure");
14+
const failure = Try.failure(error);
15+
expect(failure.ok).toBe(false);
16+
expect(failure).toBeInstanceOf(Failure);
17+
expect(() => Try.unwrap(failure)).toThrow(error);
18+
});
19+
20+
test("Try.then() propagates success like Promise.then()", () => {
21+
const result = Try.success(5).then((x) => x * 2);
22+
expect(result.ok).toBe(true);
23+
expect(result).toBeInstanceOf(Success);
24+
expect(Try.unwrap(result)).toBe(10);
25+
});
26+
27+
test("Try.then() skips failure like Promise.then()", () => {
28+
const error = new Error("Oops");
29+
const result = Try.failure(error).then((x) => (x as number) * 2);
30+
expect(result.ok).toBe(false);
31+
expect(result).toBeInstanceOf(Failure);
32+
expect(() => Try.unwrap(result)).toThrow(error);
33+
});
34+
35+
test("Try.catch() catches errors like Promise.catch()", () => {
36+
const error = new Error("Oops");
37+
const recovered = Try.failure(error).catch(() => 42);
38+
expect(recovered.ok).toBe(true);
39+
expect(recovered).toBeInstanceOf(Success);
40+
expect(Try.unwrap(recovered)).toBe(42);
41+
});
42+
43+
test("Try.finally() runs like Promise.finally()", () => {
44+
let called = false;
45+
const success = Try.success(10).finally(() => {
46+
called = true;
47+
});
48+
49+
expect(success.ok).toBe(true);
50+
expect(success).toBeInstanceOf(Success);
51+
expect(Try.unwrap(success)).toBe(10);
52+
expect(called).toBe(true);
53+
54+
called = false;
55+
const failure = Try.failure("error").finally(() => {
56+
called = true;
57+
});
58+
59+
expect(failure.ok).toBe(false);
60+
expect(failure).toBeInstanceOf(Failure);
61+
expect(called).toBe(true);
62+
});
63+
64+
test("Try.finally() does not change the result", () => {
65+
const success = Try.success(5).finally(() => {});
66+
expect(success).toBeInstanceOf(Success);
67+
expect(Try.unwrap(success)).toBe(5);
68+
69+
const failure = Try.failure("error").finally(() => {});
70+
expect(failure).toBeInstanceOf(Failure);
71+
expect(failure.ok).toBe(false);
72+
});
73+
74+
test("Try applies function and handles exceptions", () => {
75+
const success = Try.apply(() => 100);
76+
expect(success.ok).toBe(true);
77+
expect(success).toBeInstanceOf(Success);
78+
expect(Try.unwrap(success)).toBe(100);
79+
80+
const failure = Try.apply(() => {
81+
throw new Error("Oops");
82+
});
83+
expect(failure.ok).toBe(false);
84+
expect(failure).toBeInstanceOf(Failure);
85+
});
86+
87+
test("Try.promise handles async functions like Promise", async () => {
88+
const success = await Try.promise(async () => 123);
89+
expect(success).toBe(123);
90+
91+
await expect(
92+
Try.promise(async () => {
93+
throw new Error("Async Error");
94+
})
95+
).rejects.toThrow("Async Error");
96+
});
97+
98+
test("Try.success unwraps nested Trys like Promise.resolve", () => {
99+
const nested = Try.success(Try.success(50));
100+
expect(nested).toBeInstanceOf(Success);
101+
expect(Try.unwrap(nested)).toBe(50);
102+
});
103+
104+
test("Try.success unwraps deeply nested Trys", () => {
105+
const deeplyNested = Try.success(Try.success(Try.success(99)));
106+
expect(deeplyNested).toBeInstanceOf(Success);
107+
expect(Try.unwrap(deeplyNested)).toBe(99);
108+
});
109+
});

tsconfig.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@
2222
// Some stricter flags (disabled by default)
2323
"noUnusedLocals": false,
2424
"noUnusedParameters": false,
25-
"noPropertyAccessFromIndexSignature": false
25+
"noPropertyAccessFromIndexSignature": false,
26+
27+
// Paths
28+
"baseUrl": ".",
29+
"paths": {
30+
"@microlib/try": ["./dist/index.js"],
31+
"@microlib/try/*": ["./dist/*"]
32+
}
2633
}
2734
}

0 commit comments

Comments
 (0)