215 lines
7.1 KiB
TypeScript
215 lines
7.1 KiB
TypeScript
/**
|
|
* 单元测试: constants
|
|
*
|
|
* 测试应用常量的完整性和一致性
|
|
*/
|
|
|
|
import { describe, it, expect } from "vitest";
|
|
import {
|
|
APP_DISPLAY_NAME,
|
|
APP_NAME_IDENTIFIER,
|
|
APP_DATA_DIR_NAME,
|
|
DEFAULT_MCP_PROXY_PORT,
|
|
DEFAULT_FILE_SERVER_PORT,
|
|
DEFAULT_AGENT_RUNNER_PORT,
|
|
DEFAULT_LANPROXY_PORT,
|
|
DEFAULT_DEV_SERVER_PORT,
|
|
LOCALHOST_IP,
|
|
LOCALHOST_HOSTNAME,
|
|
LOCAL_HOST_URL,
|
|
DEFAULT_ANTHROPIC_API_URL,
|
|
DEFAULT_SERVER_HOST,
|
|
DEFAULT_AI_ENGINE,
|
|
isAgentEngineType,
|
|
normalizeAgentEngine,
|
|
normalizeOptionalPort,
|
|
SUPPORTED_AGENT_ENGINES,
|
|
DEFAULT_AI_MODEL,
|
|
DEFAULT_MAX_TOKENS,
|
|
DEFAULT_TEMPERATURE,
|
|
MODEL_OPTIONS,
|
|
DEFAULT_API_TIMEOUT,
|
|
DEFAULT_SSE_RETRY_DELAY,
|
|
DEFAULT_SSE_MAX_RETRY_DELAY,
|
|
DEFAULT_SSE_HEARTBEAT_INTERVAL,
|
|
DEFAULT_STARTUP_DELAY,
|
|
CLEANUP_TIMEOUT,
|
|
PROCESS_KILL_ESCALATION_TIMEOUT,
|
|
ACP_ABORT_TIMEOUT,
|
|
ACP_PROMPT_TIMEOUT,
|
|
ENGINE_DESTROY_TIMEOUT,
|
|
DEPS_SYNC_TIMEOUT,
|
|
NPM_MIRRORS,
|
|
UV_MIRRORS,
|
|
DEFAULT_MIRROR_CONFIG,
|
|
STORAGE_KEYS,
|
|
AUTH_KEYS,
|
|
} from "./constants";
|
|
|
|
describe("Constants", () => {
|
|
describe("App Identity", () => {
|
|
it("should have consistent app name", () => {
|
|
expect(APP_DISPLAY_NAME).toBe("飞天数字员工");
|
|
expect(APP_NAME_IDENTIFIER).toBe("qimingclaw");
|
|
});
|
|
|
|
it("should have app data dir name with dot prefix", () => {
|
|
expect(APP_DATA_DIR_NAME).toBe(".qimingclaw");
|
|
});
|
|
});
|
|
|
|
describe("Port Configuration", () => {
|
|
it("should have valid port numbers", () => {
|
|
expect(DEFAULT_MCP_PROXY_PORT).toBeGreaterThan(0);
|
|
expect(DEFAULT_MCP_PROXY_PORT).toBeLessThan(65536);
|
|
expect(DEFAULT_FILE_SERVER_PORT).toBe(60005);
|
|
expect(DEFAULT_AGENT_RUNNER_PORT).toBe(60006);
|
|
expect(DEFAULT_LANPROXY_PORT).toBe(60002);
|
|
expect(DEFAULT_DEV_SERVER_PORT).toBe(60173);
|
|
});
|
|
|
|
it("should have non-overlapping ports", () => {
|
|
const ports = [
|
|
DEFAULT_MCP_PROXY_PORT,
|
|
DEFAULT_FILE_SERVER_PORT,
|
|
DEFAULT_AGENT_RUNNER_PORT,
|
|
DEFAULT_LANPROXY_PORT,
|
|
DEFAULT_DEV_SERVER_PORT,
|
|
];
|
|
const uniquePorts = new Set(ports);
|
|
expect(uniquePorts.size).toBe(ports.length);
|
|
});
|
|
});
|
|
|
|
describe("Host Configuration", () => {
|
|
it("should have localhost configuration", () => {
|
|
expect(LOCALHOST_IP).toBe("127.0.0.1");
|
|
expect(LOCALHOST_HOSTNAME).toBe("localhost");
|
|
expect(LOCAL_HOST_URL).toBe("http://127.0.0.1");
|
|
});
|
|
});
|
|
|
|
describe("API URLs", () => {
|
|
it("should have valid API URLs", () => {
|
|
expect(DEFAULT_ANTHROPIC_API_URL).toMatch(/^https?:\/\//);
|
|
expect(DEFAULT_SERVER_HOST).toMatch(/^https?:\/\//);
|
|
});
|
|
});
|
|
|
|
describe("AI Configuration", () => {
|
|
it("should have valid AI engine type", () => {
|
|
expect(["claude-code", "qimingcode"]).toContain(DEFAULT_AI_ENGINE);
|
|
expect(SUPPORTED_AGENT_ENGINES).toEqual(["claude-code", "qimingcode"]);
|
|
});
|
|
|
|
it("should normalize legacy or invalid AI engine values", () => {
|
|
expect(isAgentEngineType("claude-code")).toBe(true);
|
|
expect(isAgentEngineType("qimingcode")).toBe(true);
|
|
expect(isAgentEngineType("hermes-agent")).toBe(false);
|
|
expect(normalizeAgentEngine("qimingcode")).toBe("qimingcode");
|
|
expect(normalizeAgentEngine("hermes-agent")).toBe(DEFAULT_AI_ENGINE);
|
|
expect(normalizeAgentEngine(undefined)).toBe(DEFAULT_AI_ENGINE);
|
|
});
|
|
|
|
it("should normalize optional port values", () => {
|
|
expect(normalizeOptionalPort(60001)).toBe(60001);
|
|
expect(normalizeOptionalPort("60001")).toBe(60001);
|
|
expect(normalizeOptionalPort("")).toBeUndefined();
|
|
expect(normalizeOptionalPort("abc")).toBeUndefined();
|
|
expect(normalizeOptionalPort(0)).toBeUndefined();
|
|
expect(normalizeOptionalPort(65536)).toBeUndefined();
|
|
});
|
|
|
|
it("should have non-empty model name", () => {
|
|
expect(DEFAULT_AI_MODEL).toBeTruthy();
|
|
expect(DEFAULT_AI_MODEL.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it("should have valid token limits", () => {
|
|
expect(DEFAULT_MAX_TOKENS).toBeGreaterThan(0);
|
|
});
|
|
|
|
it("should have valid temperature range", () => {
|
|
expect(DEFAULT_TEMPERATURE).toBeGreaterThanOrEqual(0);
|
|
expect(DEFAULT_TEMPERATURE).toBeLessThanOrEqual(1);
|
|
});
|
|
|
|
it("should have model options with labels and values", () => {
|
|
MODEL_OPTIONS.forEach((option) => {
|
|
expect(option.label).toBeTruthy();
|
|
expect(option.value).toBeTruthy();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("Timeout Configuration", () => {
|
|
it("should have positive timeout values", () => {
|
|
expect(DEFAULT_API_TIMEOUT).toBeGreaterThan(0);
|
|
expect(DEFAULT_SSE_RETRY_DELAY).toBeGreaterThan(0);
|
|
expect(DEFAULT_SSE_MAX_RETRY_DELAY).toBeGreaterThan(0);
|
|
expect(DEFAULT_SSE_HEARTBEAT_INTERVAL).toBeGreaterThan(0);
|
|
expect(DEFAULT_STARTUP_DELAY).toBeGreaterThan(0);
|
|
expect(CLEANUP_TIMEOUT).toBeGreaterThan(0);
|
|
expect(PROCESS_KILL_ESCALATION_TIMEOUT).toBeGreaterThan(0);
|
|
expect(ACP_ABORT_TIMEOUT).toBeGreaterThan(0);
|
|
expect(ACP_PROMPT_TIMEOUT).toBeGreaterThan(0);
|
|
expect(ENGINE_DESTROY_TIMEOUT).toBeGreaterThan(0);
|
|
expect(DEPS_SYNC_TIMEOUT).toBeGreaterThan(0);
|
|
});
|
|
|
|
it("should have max retry delay greater than initial retry delay", () => {
|
|
expect(DEFAULT_SSE_MAX_RETRY_DELAY).toBeGreaterThanOrEqual(
|
|
DEFAULT_SSE_RETRY_DELAY,
|
|
);
|
|
});
|
|
|
|
it("should have process kill escalation shorter than cleanup timeout", () => {
|
|
expect(PROCESS_KILL_ESCALATION_TIMEOUT).toBeLessThan(CLEANUP_TIMEOUT);
|
|
});
|
|
|
|
it("should have ACP abort timeout shorter than engine destroy timeout", () => {
|
|
expect(ACP_ABORT_TIMEOUT).toBeLessThanOrEqual(ENGINE_DESTROY_TIMEOUT);
|
|
});
|
|
|
|
it("should have deps sync timeout as the largest timeout", () => {
|
|
expect(DEPS_SYNC_TIMEOUT).toBeGreaterThan(ENGINE_DESTROY_TIMEOUT);
|
|
expect(DEPS_SYNC_TIMEOUT).toBeGreaterThan(CLEANUP_TIMEOUT);
|
|
});
|
|
});
|
|
|
|
describe("Mirror Configuration", () => {
|
|
it("should have npm mirror presets", () => {
|
|
expect(NPM_MIRRORS.OFFICIAL).toContain("npmjs.org");
|
|
expect(NPM_MIRRORS.TAOBAO).toContain("npmmirror");
|
|
expect(NPM_MIRRORS.TENCENT).toContain("tencent");
|
|
});
|
|
|
|
it("should have uv mirror presets", () => {
|
|
expect(UV_MIRRORS.OFFICIAL).toContain("pypi.org");
|
|
expect(UV_MIRRORS.TUNA).toContain("tsinghua");
|
|
expect(UV_MIRRORS.ALIYUN).toContain("aliyun");
|
|
expect(UV_MIRRORS.TENCENT).toContain("tencent");
|
|
});
|
|
|
|
it("should have default mirror config", () => {
|
|
expect(DEFAULT_MIRROR_CONFIG.npmRegistry).toBeTruthy();
|
|
expect(DEFAULT_MIRROR_CONFIG.uvIndexUrl).toBeTruthy();
|
|
});
|
|
});
|
|
|
|
describe("Storage Keys", () => {
|
|
it("should have all required storage keys", () => {
|
|
expect(STORAGE_KEYS.SETUP_STATE).toBe("setup_state");
|
|
expect(STORAGE_KEYS.STEP1_CONFIG).toBe("step1_config");
|
|
expect(STORAGE_KEYS.AUTH_USER).toBe("auth_user");
|
|
expect(STORAGE_KEYS.API_KEY).toBe("anthropic_api_key");
|
|
});
|
|
|
|
it("should have auth keys", () => {
|
|
expect(AUTH_KEYS.USERNAME).toBe("auth.username");
|
|
expect(AUTH_KEYS.PASSWORD).toBe("auth.password");
|
|
expect(AUTH_KEYS.SAVED_KEY).toBe("auth.saved_key");
|
|
});
|
|
});
|
|
});
|