Skip to content

Commit a30f0cc

Browse files
committed
feat: reduce project size
1 parent f79e587 commit a30f0cc

20 files changed

Lines changed: 427 additions & 170 deletions

__tests__/base64.spec.ts

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,38 @@
1-
import { expect, it } from "vitest";
1+
import { describe, expect, it } from "vitest";
22

33
import { decodeBase64, encodeBase64 } from "../src/base64.js";
4-
import { BASE64_INDEX } from "../src/constant.js";
54

6-
it("Have correct constant", () => {
7-
expect(BASE64_INDEX).toEqual([
8-
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
9-
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
10-
-1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 54, 55, 56, 57, 58, 59, 60, 61, 62,
11-
63, -1, -1, -1, -1, -1, -1, -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
12-
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1,
13-
28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
14-
47, 48, 49, 50, 51, 52, 53, -1, -1, -1, -1, -1,
15-
]);
16-
});
5+
describe("encodeBase64", () => {
6+
it("should encode byte array to base64 string", () => {
7+
expect(
8+
encodeBase64(
9+
[
10+
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
11+
0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
12+
],
13+
16,
14+
),
15+
).toEqual("..CA.uOD/eaGAOmJB.yMBu");
16+
});
1717

18-
it("Encode Base64", () => {
19-
expect(
20-
encodeBase64(
21-
[
22-
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
23-
0x0c, 0x0d, 0x0e, 0x0f, 0x10,
24-
],
25-
16,
26-
),
27-
).toEqual("..CA.uOD/eaGAOmJB.yMBu");
18+
it("should throw error for invalid length", () => {
19+
expect(() => encodeBase64([1, 2, 3], 0)).toThrow("Illegal length: 0");
20+
expect(() => encodeBase64([1, 2, 3], -1)).toThrow("Illegal length: -1");
21+
expect(() => encodeBase64([1, 2, 3], 5)).toThrow("Illegal length: 5");
22+
});
2823
});
2924

30-
it("Decode Base64", () => {
31-
expect(decodeBase64("..CA.uOD/eaGAOmJB.yMBv.", 16)).toEqual([
32-
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
33-
0x0c, 0x0d, 0x0e, 0x0f,
34-
]);
25+
describe("decodeBase64", () => {
26+
it("should decode base64 string to byte array", () => {
27+
expect(decodeBase64("..CA.uOD/eaGAOmJB.yMBv.", 16)).toEqual([
28+
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
29+
0x0c, 0x0d, 0x0e, 0x0f,
30+
]);
31+
});
32+
33+
it("should handle invalid characters gracefully", () => {
34+
const result = decodeBase64("invalid@char", 5);
35+
36+
expect(result.length).toBeLessThanOrEqual(5);
37+
});
3538
});

__tests__/compare.spec.ts

Lines changed: 67 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { expect, it } from "vitest";
1+
import { describe, expect, it } from "vitest";
22

33
import {
44
compare,
@@ -9,29 +9,75 @@ import {
99
hashSync,
1010
} from "../src/index.js";
1111

12-
it("Compare sync", () => {
13-
const salt1 = genSaltSync();
14-
const hash1 = hashSync("hello", salt1);
15-
const salt2 = genSaltSync().replace(/\$2b\$/, "$2y$");
16-
const hash2 = hashSync("world", salt2);
12+
describe("compare", () => {
13+
it("should return true for valid password-hash pairs", async () => {
14+
const salt1 = await genSalt();
15+
const hash1 = await hash("hello", salt1);
16+
const salt2 = (await genSalt()).replace(/\$2b\$/, "$2y$");
17+
const hash2 = await hash("world", salt2);
1718

18-
expect(hash1.substring(0, 4)).toBe("$2b$");
19-
expect(compareSync("hello", hash1)).toBe(true);
20-
expect(compareSync("hello", hash2)).toBe(false);
19+
expect(await compare("hello", hash1)).toBe(true);
20+
expect(await compare("hello", hash2)).toBe(false);
21+
expect(await compare("world", hash1)).toBe(false);
22+
expect(await compare("world", hash2)).toBe(true);
23+
});
2124

22-
expect(hash2.substring(0, 4)).toBe("$2y$");
23-
expect(compareSync("world", hash1)).toBe(false);
24-
expect(compareSync("world", hash2)).toBe(true);
25+
it("should reject with error for invalid argument types", async () => {
26+
// @ts-expect-error: error type check
27+
await expect(compare(123, "hash")).rejects.toThrow(
28+
"Illegal arguments: number, string",
29+
);
30+
// @ts-expect-error: error type check
31+
await expect(compare("content", 123)).rejects.toThrow(
32+
"Illegal arguments: string, number",
33+
);
34+
// @ts-expect-error: error type check
35+
await expect(compare(123, 456)).rejects.toThrow(
36+
"Illegal arguments: number, number",
37+
);
38+
});
39+
40+
it("should resolve false for invalid hash length", async () => {
41+
await expect(compare("hello", "invalid")).resolves.toBe(false);
42+
await expect(compare("hello", "short")).resolves.toBe(false);
43+
await expect(compare("hello", "a".repeat(59))).resolves.toBe(false);
44+
});
2545
});
2646

27-
it("Compare async", async () => {
28-
const salt1 = await genSalt();
29-
const hash1 = await hash("hello", salt1);
30-
const salt2 = (await genSalt()).replace(/\$2b\$/, "$2y$");
31-
const hash2 = await hash("world", salt2);
47+
describe("compareSync", () => {
48+
it("should return true for valid password-hash pairs", () => {
49+
const salt1 = genSaltSync();
50+
const hash1 = hashSync("hello", salt1);
51+
const salt2 = genSaltSync().replace(/\$2b\$/, "$2y$");
52+
const hash2 = hashSync("world", salt2);
53+
54+
expect(hash1.substring(0, 4)).toBe("$2b$");
55+
expect(compareSync("hello", hash1)).toBe(true);
56+
expect(compareSync("hello", hash2)).toBe(false);
57+
58+
expect(hash2.substring(0, 4)).toBe("$2y$");
59+
expect(compareSync("world", hash1)).toBe(false);
60+
expect(compareSync("world", hash2)).toBe(true);
61+
});
62+
63+
it("should throw error for invalid argument types", () => {
64+
// @ts-expect-error: error type check
65+
expect(() => compareSync(123, "hash")).toThrow(
66+
"Illegal arguments: number, string",
67+
);
68+
// @ts-expect-error: error type check
69+
expect(() => compareSync("content", 123)).toThrow(
70+
"Illegal arguments: string, number",
71+
);
72+
// @ts-expect-error: error type check
73+
expect(() => compareSync(123, 456)).toThrow(
74+
"Illegal arguments: number, number",
75+
);
76+
});
3277

33-
expect(await compare("hello", hash1)).toBe(true);
34-
expect(await compare("hello", hash2)).toBe(false);
35-
expect(await compare("world", hash1)).toBe(false);
36-
expect(await compare("world", hash2)).toBe(true);
78+
it("should return false for invalid hash length", () => {
79+
expect(compareSync("hello", "invalid")).toBe(false);
80+
expect(compareSync("hello", "short")).toBe(false);
81+
expect(compareSync("hello", "a".repeat(59))).toBe(false);
82+
});
3783
});

__tests__/hash.spec.ts

Lines changed: 87 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,95 @@
1-
import { expect, it } from "vitest";
1+
import { describe, expect, it } from "vitest";
22

33
import { hash, hashSync } from "../src/index.js";
44

5-
it("Hash sync", () => {
6-
expect(hashSync("hello", 10)).not.toEqual(hashSync("hello", 10));
7-
expect(hashSync("中国我爱你!", 10)).not.toEqual(
8-
hashSync("中国我爱你!", 10),
9-
);
5+
describe("hash", () => {
6+
it("should generate hash for valid inputs", async () => {
7+
const hash1 = await hash("hello", 10);
8+
const hash2 = await hash("hello", 10);
9+
const hash3 = await hash("中国我爱你!", 10);
10+
const hash4 = await hash("中国我爱你!", 10);
11+
12+
expect(hash1).toBeTypeOf("string");
13+
expect(hash2).toBeTypeOf("string");
14+
expect(hash3).toBeTypeOf("string");
15+
expect(hash4).toBeTypeOf("string");
16+
expect(hash1).not.toEqual(hash2);
17+
expect(hash3).not.toEqual(hash4);
18+
});
19+
20+
it("should reject for invalid argument types", async () => {
21+
// @ts-expect-error: error type check
22+
await expect(hash(123, 10)).rejects.toThrow(
23+
"Invalid content / salt: not a string",
24+
);
25+
await expect(hash("hello", "invalid")).rejects.toThrow(
26+
"Invalid salt version: in",
27+
);
28+
});
29+
30+
it("should reject for invalid salt format", async () => {
31+
await expect(hash("hello", "invalid")).rejects.toThrow(
32+
"Invalid salt version: in",
33+
);
34+
await expect(hash("hello", "$1$")).rejects.toThrow(
35+
"Invalid salt version: $1",
36+
);
37+
await expect(hash("hello", "$2x$10$")).rejects.toThrow(
38+
"Invalid salt revision: x$",
39+
);
40+
await expect(hash("hello", "$2a$")).rejects.toThrow(
41+
"Illegal salt length: 0 != 16",
42+
);
43+
await expect(hash("hello", "$2$10$validsalthere")).rejects.toThrow(
44+
"Illegal salt length: 9 != 16",
45+
);
46+
await expect(hash("hello", "$2a$1Z$validsalthere")).rejects.toThrow(
47+
"Illegal salt length: 9 != 16",
48+
);
49+
});
1050
});
1151

12-
it("Hash async", () => {
13-
void hash("hello", 10).then((hash) => {
14-
expect(hash).toBeTypeOf("string");
52+
describe("hashSync", () => {
53+
it("should generate hash for valid inputs", () => {
54+
const hash1 = hashSync("hello", 10);
55+
const hash2 = hashSync("hello", 10);
56+
const hash3 = hashSync("中国我爱你!", 10);
57+
const hash4 = hashSync("中国我爱你!", 10);
58+
59+
expect(hash1).toBeTypeOf("string");
60+
expect(hash2).toBeTypeOf("string");
61+
expect(hash3).toBeTypeOf("string");
62+
expect(hash4).toBeTypeOf("string");
63+
expect(hash1).not.toEqual(hash2);
64+
expect(hash3).not.toEqual(hash4);
1565
});
16-
void hash("中国我爱你!", 10).then((hash) => {
17-
expect(hash).toBeTypeOf("string");
66+
67+
it("should throw error for invalid argument types", () => {
68+
// @ts-expect-error: error type check
69+
expect(() => hashSync(123, 10)).toThrow(
70+
"Invalid content / salt: not a string",
71+
);
72+
expect(() => hashSync("hello", "invalid")).toThrow(
73+
"Invalid salt version: in",
74+
);
75+
});
76+
77+
it("should throw error for invalid salt format", () => {
78+
expect(() => hashSync("hello", "invalid")).toThrow(
79+
"Invalid salt version: in",
80+
);
81+
expect(() => hashSync("hello", "$1$")).toThrow("Invalid salt version: $1");
82+
expect(() => hashSync("hello", "$2x$10$valid_salt_here")).toThrow(
83+
"Invalid salt revision: x$",
84+
);
85+
expect(() => hashSync("hello", "$2a$0")).toThrow(
86+
"Illegal salt length: 0 != 16",
87+
);
88+
expect(() => hashSync("hello", "$2$10$validsalthere")).toThrow(
89+
"Illegal salt length: 9 != 16",
90+
);
91+
expect(() => hashSync("hello", "$2a$1Z$validsalthere")).toThrow(
92+
"Illegal salt length: 9 != 16",
93+
);
1894
});
1995
});

__tests__/helper.spec.ts

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,61 @@
1-
import { expect, it } from "vitest";
1+
import { describe, expect, it } from "vitest";
22

3-
import { genSaltSync, getRounds, getSalt, hashSync } from "../src/index.js";
3+
import {
4+
genSaltSync,
5+
getRounds,
6+
getSalt,
7+
hashSync,
8+
truncates,
9+
} from "../src/index.js";
410

5-
it("Get salt", () => {
6-
const hash1 = hashSync("hello", genSaltSync());
7-
const salt = getSalt(hash1);
8-
const hash2 = hashSync("hello", salt);
11+
describe("getSalt", () => {
12+
it("should work", () => {
13+
const hash1 = hashSync("hello", genSaltSync());
14+
const salt = getSalt(hash1);
15+
const hash2 = hashSync("hello", salt);
916

10-
expect(hash1).toEqual(hash2);
17+
expect(hash1).toEqual(hash2);
18+
});
19+
20+
it("should throw error for invalid argument types", () => {
21+
// @ts-expect-error: error type check
22+
expect(() => getSalt(123)).toThrow("Illegal arguments: number");
23+
// @ts-expect-error: error type check
24+
expect(() => getSalt(null)).toThrow("Illegal arguments: object");
25+
});
26+
27+
it("should throw error for invalid hash length", () => {
28+
expect(() => getSalt("invalid")).toThrow("Illegal hash length: 7 != 60");
29+
expect(() => getSalt("short")).toThrow("Illegal hash length: 5 != 60");
30+
});
31+
});
32+
33+
describe("getRounds", () => {
34+
it("should work", () => {
35+
const hash1 = hashSync("hello", genSaltSync());
36+
37+
expect(getRounds(hash1)).toBe(10);
38+
});
39+
40+
it("should throw error for invalid argument types", () => {
41+
// @ts-expect-error: error type check
42+
expect(() => getRounds(123)).toThrow("Illegal arguments: number");
43+
// @ts-expect-error: error type check
44+
expect(() => getRounds(null)).toThrow("Illegal arguments: object");
45+
});
1146
});
1247

13-
it("Get rounds", () => {
14-
const hash1 = hashSync("hello", genSaltSync());
48+
describe("truncates", () => {
49+
it("should work", () => {
50+
expect(truncates("hello")).toBe(false);
51+
expect(truncates("a".repeat(72))).toBe(false);
52+
expect(truncates("a".repeat(73))).toBe(true);
53+
});
1554

16-
expect(getRounds(hash1)).toBe(10);
55+
it("should throw error for invalid argument types", () => {
56+
// @ts-expect-error: error type check
57+
expect(() => truncates(123)).toThrow("Illegal arguments: number");
58+
// @ts-expect-error: error type check
59+
expect(() => truncates(null)).toThrow("Illegal arguments: object");
60+
});
1761
});

__tests__/nextTick.spec.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { describe, expect, it } from "vitest";
2+
3+
import { nextTick } from "../src/nextTick/node.js";
4+
5+
describe("nextTick", () => {
6+
it("should work correctly", () =>
7+
new Promise<void>((resolve) => {
8+
let executed = false;
9+
10+
nextTick(() => {
11+
executed = true;
12+
expect(executed).toBe(true);
13+
resolve();
14+
});
15+
16+
expect(executed).toBe(false);
17+
}));
18+
19+
it("should use setImmediate in Node.js", () => {
20+
// Test that nextTick is using the correct function
21+
expect(typeof nextTick).toBe("function");
22+
});
23+
});

__tests__/progress.spec.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
import { expect, it } from "vitest";
1+
import { describe, expect, it } from "vitest";
22

33
import { genSaltSync, hash } from "../src/index.js";
44

5-
it("Should show progress", () => {
6-
const salt = genSaltSync(12);
5+
describe("hash progress callback", () => {
6+
it("should show progress", async () => {
7+
const salt = genSaltSync(12);
78

8-
const progress: number[] = [];
9+
const progress: number[] = [];
910

10-
return hash("hello world", salt, (percent) => {
11-
progress.push(percent);
12-
}).then((hash) => {
13-
expect(typeof hash === "string").toBe(true);
11+
const result = await hash("hello world", salt, (percent) => {
12+
progress.push(percent);
13+
});
14+
15+
expect(typeof result === "string").toBe(true);
1416
expect(progress.length).toBeGreaterThan(2);
1517
expect(progress[0]).toBe(0);
1618
expect(progress[progress.length - 1]).toBe(1);

0 commit comments

Comments
 (0)