test: 添加一大堆测试文件

This commit is contained in:
claude-code-best
2026-04-02 20:28:08 +08:00
parent 6f5623b26c
commit ce29527a67
33 changed files with 3502 additions and 329 deletions

View File

@@ -0,0 +1,165 @@
import { mock, describe, expect, test } from "bun:test";
mock.module("src/utils/slowOperations.js", () => ({
jsonStringify: (v: unknown) => JSON.stringify(v),
}));
mock.module("src/services/analytics/growthbook.js", () => ({
getFeatureValue_CACHED_MAY_BE_STALE: () => false,
}));
const {
shortRequestId,
truncateForPreview,
PERMISSION_REPLY_RE,
createChannelPermissionCallbacks,
} = await import("../channelPermissions");
describe("shortRequestId", () => {
test("returns 5-char string from tool use ID", () => {
const result = shortRequestId("toolu_abc123");
expect(result).toHaveLength(5);
});
test("is deterministic (same input = same output)", () => {
const a = shortRequestId("toolu_abc123");
const b = shortRequestId("toolu_abc123");
expect(a).toBe(b);
});
test("different inputs produce different outputs", () => {
const a = shortRequestId("toolu_aaa");
const b = shortRequestId("toolu_bbb");
expect(a).not.toBe(b);
});
test("result contains only valid letters (no 'l')", () => {
const validChars = new Set("abcdefghijkmnopqrstuvwxyz");
for (let i = 0; i < 50; i++) {
const result = shortRequestId(`toolu_${i}`);
for (const ch of result) {
expect(validChars.has(ch)).toBe(true);
}
}
});
test("handles empty string", () => {
const result = shortRequestId("");
expect(result).toHaveLength(5);
});
});
describe("truncateForPreview", () => {
test("returns JSON string for object input", () => {
const result = truncateForPreview({ key: "value" });
expect(result).toBe('{"key":"value"}');
});
test("truncates to <=200 chars with ellipsis when input is long", () => {
const longObj = { data: "x".repeat(300) };
const result = truncateForPreview(longObj);
expect(result.length).toBeLessThanOrEqual(203); // 200 + '…'
expect(result.endsWith("…")).toBe(true);
});
test("returns short input unchanged", () => {
const result = truncateForPreview({ a: 1 });
expect(result).toBe('{"a":1}');
expect(result.endsWith("…")).toBe(false);
});
test("handles string input", () => {
const result = truncateForPreview("hello");
expect(result).toBe('"hello"');
});
test("handles null input", () => {
const result = truncateForPreview(null);
expect(result).toBe("null");
});
test("handles undefined input", () => {
const result = truncateForPreview(undefined);
// JSON.stringify(undefined) returns undefined, then .length throws → catch returns '(unserializable)'
expect(result).toBe("(unserializable)");
});
});
describe("PERMISSION_REPLY_RE", () => {
test("matches 'y abcde'", () => {
expect(PERMISSION_REPLY_RE.test("y abcde")).toBe(true);
});
test("matches 'yes abcde'", () => {
expect(PERMISSION_REPLY_RE.test("yes abcde")).toBe(true);
});
test("matches 'n abcde'", () => {
expect(PERMISSION_REPLY_RE.test("n abcde")).toBe(true);
});
test("matches 'no abcde'", () => {
expect(PERMISSION_REPLY_RE.test("no abcde")).toBe(true);
});
test("is case-insensitive", () => {
expect(PERMISSION_REPLY_RE.test("Y abcde")).toBe(true);
expect(PERMISSION_REPLY_RE.test("YES abcde")).toBe(true);
});
test("does not match without ID", () => {
expect(PERMISSION_REPLY_RE.test("yes")).toBe(false);
});
test("captures the ID from reply", () => {
const match = "y abcde".match(PERMISSION_REPLY_RE);
expect(match?.[2]).toBe("abcde");
});
});
describe("createChannelPermissionCallbacks", () => {
test("resolve returns false for unknown request ID", () => {
const cb = createChannelPermissionCallbacks();
expect(cb.resolve("unknown-id", "allow", "server")).toBe(false);
});
test("onResponse + resolve triggers handler", () => {
const cb = createChannelPermissionCallbacks();
let received: any = null;
cb.onResponse("test-id", (response) => {
received = response;
});
expect(cb.resolve("test-id", "allow", "test-server")).toBe(true);
expect(received).toEqual({
behavior: "allow",
fromServer: "test-server",
});
});
test("onResponse unsubscribe prevents resolve", () => {
const cb = createChannelPermissionCallbacks();
let called = false;
const unsub = cb.onResponse("test-id", () => {
called = true;
});
unsub();
expect(cb.resolve("test-id", "allow", "server")).toBe(false);
expect(called).toBe(false);
});
test("duplicate resolve returns false (already consumed)", () => {
const cb = createChannelPermissionCallbacks();
cb.onResponse("test-id", () => {});
expect(cb.resolve("test-id", "allow", "server")).toBe(true);
expect(cb.resolve("test-id", "allow", "server")).toBe(false);
});
test("is case-insensitive for request IDs", () => {
const cb = createChannelPermissionCallbacks();
let received: any = null;
cb.onResponse("ABC", (response) => {
received = response;
});
expect(cb.resolve("abc", "deny", "server")).toBe(true);
expect(received?.behavior).toBe("deny");
});
});