Skip to content

Commit 9b0699e

Browse files
committed
fix: resolve errors and add unit test
1 parent a269099 commit 9b0699e

File tree

4 files changed

+88
-18
lines changed

4 files changed

+88
-18
lines changed

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@castdrian/kdapi",
3-
"version": "0.3.1",
3+
"version": "0.3.2",
44
"type": "module",
55
"description": "kpop idol and group profiles dataset generator",
66
"main": "dist/index.js",
@@ -21,7 +21,9 @@
2121
"scrape:prod": "bun src/cli.ts scrape --delay 4000 --batch-size 5 --cache",
2222
"scrape:force": "bun src/cli.ts scrape --delay 4000 --batch-size 5 --force",
2323
"build": "bun build ./src/index.ts --outdir ./dist --target node && tsc --project tsconfig.build.json",
24-
"prepublishOnly": "bun run build"
24+
"prepublishOnly": "bun run build",
25+
"test": "bun test",
26+
"test:watch": "bun test --watch"
2527
},
2628
"devDependencies": {
2729
"@types/uuid": "^10.0.0",

src/index.ts

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,11 @@ idolSearcher.indexEntities(
3838
entity.names.japanese,
3939
entity.names.chinese,
4040
// Add group names to search terms
41-
...(entity.groups
42-
?.flatMap((g) => [
43-
g.name, // Group name by itself
44-
`${entity.names.stage} ${g.name}`, // "Name Group"
45-
`${g.name} ${entity.names.stage}`, // "Group Name"
46-
]) || []),
41+
...(entity.groups?.flatMap((g) => [
42+
g.name, // Group name by itself
43+
`${entity.names.stage} ${g.name}`, // "Name Group"
44+
`${g.name} ${entity.names.stage}`, // "Group Name"
45+
]) || []),
4746
].filter((name): name is string => name !== null),
4847
);
4948

@@ -52,15 +51,15 @@ groupSearcher.indexEntities(
5251
(entity) => entity.id,
5352
(entity) =>
5453
[
55-
entity.groupInfo.names.stage,
56-
entity.groupInfo.names.korean,
57-
entity.groupInfo.names.japanese,
58-
entity.groupInfo.names.chinese,
59-
entity.groupInfo.fandomName,
54+
entity.groupInfo?.names?.stage,
55+
entity.groupInfo?.names?.korean,
56+
entity.groupInfo?.names?.japanese,
57+
entity.groupInfo?.names?.chinese,
58+
entity.groupInfo?.fandomName,
6059
entity.company?.current,
61-
...(entity.company?.history.map((h) => h.name) || []),
62-
...entity.memberHistory.currentMembers.map((m) => m.name),
63-
...(entity.memberHistory.formerMembers?.map((m) => m.name) || []),
60+
...(entity.company?.history ?? []).map((h) => h.name),
61+
...(entity.memberHistory?.currentMembers ?? []).map((m) => m.name),
62+
...(entity.memberHistory?.formerMembers ?? []).map((m) => m.name),
6463
].filter((name): name is string => name !== null),
6564
);
6665

test/search.test.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { describe, expect, test } from "bun:test";
2+
import { type Idol, type Group, search } from "@src/index";
3+
4+
describe("Fuzzy Search", () => {
5+
const testJapaneseName = "ステイシー";
6+
7+
test("should handle null company data", () => {
8+
const results = search("company");
9+
expect(results).toBeDefined();
10+
// Should not throw any errors
11+
});
12+
13+
test("should search by idol name", () => {
14+
const results = search("sumin");
15+
expect(results.length).toBeGreaterThan(0);
16+
expect(results.some((r) => r.type === "idol")).toBe(true);
17+
});
18+
19+
test("should search by idol name + group", () => {
20+
const results = search("sumin stayc");
21+
expect(results.length).toBeGreaterThan(0);
22+
expect(
23+
results.some(
24+
(r) =>
25+
r.type === "idol" &&
26+
(r.item as Idol).groups?.some((g) => g.name.toLowerCase().includes("fromis")),
27+
),
28+
).toBe(true);
29+
});
30+
31+
test("should search by group name", () => {
32+
const results = search("stayc");
33+
expect(results.length).toBeGreaterThan(0);
34+
expect(results.some((r) => r.type === "group")).toBe(true);
35+
});
36+
37+
test("should handle Korean characters", () => {
38+
const results = search("스테이씨");
39+
expect(results.length).toBeGreaterThan(0);
40+
});
41+
42+
test("should handle Japanese characters", () => {
43+
const results = search(testJapaneseName);
44+
expect(results.length).toBeGreaterThan(0);
45+
expect(
46+
results.some(
47+
(r) =>
48+
r.type === "group" &&
49+
(r.item as Group).groupInfo?.names?.stage
50+
?.toLowerCase()
51+
.includes("twice"),
52+
),
53+
).toBe(true);
54+
});
55+
56+
test("should handle empty/null values", () => {
57+
expect(() => search("")).not.toThrow();
58+
expect(() => search(" ")).not.toThrow();
59+
});
60+
61+
test("should filter by type", () => {
62+
const idolResults = search("jin", { type: "idol" });
63+
expect(idolResults.every((r) => r.type === "idol")).toBe(true);
64+
65+
const groupResults = search("bts", { type: "group" });
66+
expect(groupResults.every((r) => r.type === "group")).toBe(true);
67+
});
68+
});

tsconfig.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@
2222
]
2323
},
2424
"outDir": "dist",
25-
"rootDir": "src",
25+
"rootDir": ".",
2626
"declaration": true,
2727
"emitDeclarationOnly": true
2828
},
2929
"include": [
30-
"src/**/*"
30+
"src/**/*",
31+
"test/**/*"
3132
],
3233
"exclude": [
3334
"node_modules",

0 commit comments

Comments
 (0)