Skip to content

Commit 2586cc6

Browse files
authored
Merge pull request #6815 from TIANQIAN1238/feat-utils-unit-tests
test: add unit tests for pure helpers in app/utils
2 parents 89b8f26 + 243a6ea commit 2586cc6

1 file changed

Lines changed: 141 additions & 0 deletions

File tree

test/utils.test.ts

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import {
2+
trimTopic,
3+
semverCompare,
4+
getMessageTextContent,
5+
getMessageTextContentWithoutThinking,
6+
getMessageImages,
7+
isDalle3,
8+
getModelSizes,
9+
supportsCustomSize,
10+
} from "../app/utils";
11+
import { RequestMessage } from "../app/client/api";
12+
13+
describe("trimTopic", () => {
14+
test("removes wrapping quotes and asterisks", () => {
15+
expect(trimTopic('"Hello"')).toBe("Hello");
16+
expect(trimTopic("“Hello”")).toBe("Hello");
17+
expect(trimTopic("*Hello*")).toBe("Hello");
18+
expect(trimTopic('"*Title*"')).toBe("Title");
19+
});
20+
21+
test("removes trailing punctuation (CJK and ASCII)", () => {
22+
expect(trimTopic("你好。")).toBe("你好");
23+
expect(trimTopic("Are you sure?")).toBe("Are you sure");
24+
expect(trimTopic("Hello, world.")).toBe("Hello, world");
25+
});
26+
27+
test("keeps inner punctuation and returns empty string untouched", () => {
28+
expect(trimTopic("a, b, c")).toBe("a, b, c");
29+
expect(trimTopic("")).toBe("");
30+
});
31+
});
32+
33+
describe("semverCompare", () => {
34+
test("returns 0 for equal versions", () => {
35+
expect(semverCompare("1.0.0", "1.0.0")).toBe(0);
36+
});
37+
38+
test("compares numerically, not lexicographically", () => {
39+
expect(semverCompare("1.10.0", "1.2.0")).toBeGreaterThan(0);
40+
expect(semverCompare("1.2.0", "1.10.0")).toBeLessThan(0);
41+
});
42+
43+
test("treats a prerelease as lower than its release", () => {
44+
expect(semverCompare("1.0.0", "1.0.0-beta")).toBe(1);
45+
expect(semverCompare("1.0.0-beta", "1.0.0")).toBe(-1);
46+
});
47+
});
48+
49+
describe("getMessageTextContent", () => {
50+
test("returns plain string content as-is", () => {
51+
const msg: RequestMessage = { role: "user", content: "hello" };
52+
expect(getMessageTextContent(msg)).toBe("hello");
53+
});
54+
55+
test("returns the first text part of multimodal content", () => {
56+
const msg: RequestMessage = {
57+
role: "user",
58+
content: [
59+
{ type: "image_url", image_url: { url: "http://img" } },
60+
{ type: "text", text: "a caption" },
61+
],
62+
};
63+
expect(getMessageTextContent(msg)).toBe("a caption");
64+
});
65+
66+
test("returns empty string when there is no text part", () => {
67+
const msg: RequestMessage = {
68+
role: "user",
69+
content: [{ type: "image_url", image_url: { url: "http://img" } }],
70+
};
71+
expect(getMessageTextContent(msg)).toBe("");
72+
});
73+
});
74+
75+
describe("getMessageTextContentWithoutThinking", () => {
76+
test("drops thinking lines that start with '> '", () => {
77+
const msg: RequestMessage = {
78+
role: "assistant",
79+
content: "> reasoning step\nfinal answer",
80+
};
81+
expect(getMessageTextContentWithoutThinking(msg)).toBe("final answer");
82+
});
83+
84+
test("drops blank lines and trims the result", () => {
85+
const msg: RequestMessage = {
86+
role: "assistant",
87+
content: "\n> thinking\n\nline one\nline two\n",
88+
};
89+
expect(getMessageTextContentWithoutThinking(msg)).toBe(
90+
"line one\nline two",
91+
);
92+
});
93+
});
94+
95+
describe("getMessageImages", () => {
96+
test("returns an empty array for string content", () => {
97+
const msg: RequestMessage = { role: "user", content: "no images here" };
98+
expect(getMessageImages(msg)).toEqual([]);
99+
});
100+
101+
test("collects all image urls from multimodal content", () => {
102+
const msg: RequestMessage = {
103+
role: "user",
104+
content: [
105+
{ type: "image_url", image_url: { url: "http://a" } },
106+
{ type: "text", text: "between" },
107+
{ type: "image_url", image_url: { url: "http://b" } },
108+
],
109+
};
110+
expect(getMessageImages(msg)).toEqual(["http://a", "http://b"]);
111+
});
112+
});
113+
114+
describe("isDalle3", () => {
115+
test("matches only the exact dall-e-3 model id", () => {
116+
expect(isDalle3("dall-e-3")).toBe(true);
117+
expect(isDalle3("dall-e-2")).toBe(false);
118+
expect(isDalle3("gpt-4")).toBe(false);
119+
});
120+
});
121+
122+
describe("getModelSizes / supportsCustomSize", () => {
123+
test("returns dall-e-3 sizes", () => {
124+
expect(getModelSizes("dall-e-3")).toEqual([
125+
"1024x1024",
126+
"1792x1024",
127+
"1024x1792",
128+
]);
129+
expect(supportsCustomSize("dall-e-3")).toBe(true);
130+
});
131+
132+
test("returns cogview sizes (case-insensitive match)", () => {
133+
expect(getModelSizes("CogView-3")).toContain("768x1344");
134+
expect(supportsCustomSize("cogview-3")).toBe(true);
135+
});
136+
137+
test("returns no sizes for models without custom sizing", () => {
138+
expect(getModelSizes("gpt-4")).toEqual([]);
139+
expect(supportsCustomSize("gpt-4")).toBe(false);
140+
});
141+
});

0 commit comments

Comments
 (0)