mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-18 09:07:26 +00:00
test: remove duplicated scenario scaffolding across runtime tests
This commit is contained in:
@@ -359,9 +359,8 @@ describe("runCronIsolatedAgentTurn — skill filter", () => {
|
||||
"nvidia/deepseek-ai/deepseek-v3.2",
|
||||
];
|
||||
|
||||
it("preserves defaults when agent overrides primary as string", async () => {
|
||||
resolveAgentConfigMock.mockReturnValue({ model: "anthropic/claude-sonnet-4-5" });
|
||||
|
||||
async function expectPrimaryOverridePreservesDefaults(modelOverride: unknown) {
|
||||
resolveAgentConfigMock.mockReturnValue({ model: modelOverride });
|
||||
const result = await runCronIsolatedAgentTurn(
|
||||
makeParams({
|
||||
cfg: {
|
||||
@@ -383,34 +382,14 @@ describe("runCronIsolatedAgentTurn — skill filter", () => {
|
||||
| undefined;
|
||||
expect(model?.primary).toBe("anthropic/claude-sonnet-4-5");
|
||||
expect(model?.fallbacks).toEqual(defaultFallbacks);
|
||||
}
|
||||
|
||||
it("preserves defaults when agent overrides primary as string", async () => {
|
||||
await expectPrimaryOverridePreservesDefaults("anthropic/claude-sonnet-4-5");
|
||||
});
|
||||
|
||||
it("preserves defaults when agent overrides primary in object form", async () => {
|
||||
resolveAgentConfigMock.mockReturnValue({
|
||||
model: { primary: "anthropic/claude-sonnet-4-5" },
|
||||
});
|
||||
|
||||
const result = await runCronIsolatedAgentTurn(
|
||||
makeParams({
|
||||
cfg: {
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "openai-codex/gpt-5.3-codex", fallbacks: defaultFallbacks },
|
||||
},
|
||||
},
|
||||
},
|
||||
agentId: "scout",
|
||||
}),
|
||||
);
|
||||
|
||||
expect(result.status).toBe("ok");
|
||||
expect(runWithModelFallbackMock).toHaveBeenCalledOnce();
|
||||
const callCfg = runWithModelFallbackMock.mock.calls[0][0].cfg;
|
||||
const model = callCfg?.agents?.defaults?.model as
|
||||
| { primary?: string; fallbacks?: string[] }
|
||||
| undefined;
|
||||
expect(model?.primary).toBe("anthropic/claude-sonnet-4-5");
|
||||
expect(model?.fallbacks).toEqual(defaultFallbacks);
|
||||
await expectPrimaryOverridePreservesDefaults({ primary: "anthropic/claude-sonnet-4-5" });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -40,6 +40,29 @@ function createMockSessionContent(
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
async function runNewWithPreviousSessionEntry(params: {
|
||||
tempDir: string;
|
||||
previousSessionEntry: { sessionId: string; sessionFile?: string };
|
||||
cfg?: OpenClawConfig;
|
||||
}): Promise<{ files: string[]; memoryContent: string }> {
|
||||
const event = createHookEvent("command", "new", "agent:main:main", {
|
||||
cfg:
|
||||
params.cfg ??
|
||||
({
|
||||
agents: { defaults: { workspace: params.tempDir } },
|
||||
} satisfies OpenClawConfig),
|
||||
previousSessionEntry: params.previousSessionEntry,
|
||||
});
|
||||
|
||||
await handler(event);
|
||||
|
||||
const memoryDir = path.join(params.tempDir, "memory");
|
||||
const files = await fs.readdir(memoryDir);
|
||||
const memoryContent =
|
||||
files.length > 0 ? await fs.readFile(path.join(memoryDir, files[0]), "utf-8") : "";
|
||||
return { files, memoryContent };
|
||||
}
|
||||
|
||||
async function runNewWithPreviousSession(params: {
|
||||
sessionContent: string;
|
||||
cfg?: (tempDir: string) => OpenClawConfig;
|
||||
@@ -60,21 +83,14 @@ async function runNewWithPreviousSession(params: {
|
||||
agents: { defaults: { workspace: tempDir } },
|
||||
} satisfies OpenClawConfig);
|
||||
|
||||
const event = createHookEvent("command", "new", "agent:main:main", {
|
||||
const { files, memoryContent } = await runNewWithPreviousSessionEntry({
|
||||
tempDir,
|
||||
cfg,
|
||||
previousSessionEntry: {
|
||||
sessionId: "test-123",
|
||||
sessionFile,
|
||||
},
|
||||
});
|
||||
|
||||
await handler(event);
|
||||
|
||||
const memoryDir = path.join(tempDir, "memory");
|
||||
const files = await fs.readdir(memoryDir);
|
||||
const memoryContent =
|
||||
files.length > 0 ? await fs.readFile(path.join(memoryDir, files[0]), "utf-8") : "";
|
||||
|
||||
return { tempDir, files, memoryContent };
|
||||
}
|
||||
|
||||
@@ -277,25 +293,14 @@ describe("session-memory hook", () => {
|
||||
content: resetContent,
|
||||
});
|
||||
|
||||
const cfg = {
|
||||
agents: { defaults: { workspace: tempDir } },
|
||||
} satisfies OpenClawConfig;
|
||||
|
||||
const event = createHookEvent("command", "new", "agent:main:main", {
|
||||
cfg,
|
||||
const { memoryContent } = await runNewWithPreviousSessionEntry({
|
||||
tempDir,
|
||||
previousSessionEntry: {
|
||||
sessionId: "test-123",
|
||||
sessionFile: activeSessionFile,
|
||||
},
|
||||
});
|
||||
|
||||
await handler(event);
|
||||
|
||||
const memoryDir = path.join(tempDir, "memory");
|
||||
const files = await fs.readdir(memoryDir);
|
||||
expect(files.length).toBe(1);
|
||||
const memoryContent = await fs.readFile(path.join(memoryDir, files[0]), "utf-8");
|
||||
|
||||
expect(memoryContent).toContain("user: Message from rotated transcript");
|
||||
expect(memoryContent).toContain("assistant: Recovered from reset fallback");
|
||||
});
|
||||
@@ -408,25 +413,14 @@ describe("session-memory hook", () => {
|
||||
]),
|
||||
});
|
||||
|
||||
const cfg = {
|
||||
agents: { defaults: { workspace: tempDir } },
|
||||
} satisfies OpenClawConfig;
|
||||
|
||||
const event = createHookEvent("command", "new", "agent:main:main", {
|
||||
cfg,
|
||||
const { memoryContent } = await runNewWithPreviousSessionEntry({
|
||||
tempDir,
|
||||
previousSessionEntry: {
|
||||
sessionId: "test-123",
|
||||
sessionFile: activeSessionFile,
|
||||
},
|
||||
});
|
||||
|
||||
await handler(event);
|
||||
|
||||
const memoryDir = path.join(tempDir, "memory");
|
||||
const files = await fs.readdir(memoryDir);
|
||||
expect(files.length).toBe(1);
|
||||
const memoryContent = await fs.readFile(path.join(memoryDir, files[0]), "utf-8");
|
||||
|
||||
expect(memoryContent).toContain("user: Newest rotated transcript");
|
||||
expect(memoryContent).toContain("assistant: Newest summary");
|
||||
expect(memoryContent).not.toContain("Older rotated transcript");
|
||||
|
||||
@@ -48,16 +48,19 @@ function resolve(params: {
|
||||
});
|
||||
}
|
||||
|
||||
function buildDispatchContextPayload(params: { cfg: OpenClawConfig; message: IMessagePayload }) {
|
||||
const { cfg, message } = params;
|
||||
const groupHistories = new Map();
|
||||
function resolveDispatchDecision(params: {
|
||||
cfg: OpenClawConfig;
|
||||
message: IMessagePayload;
|
||||
groupHistories?: Parameters<typeof resolveIMessageInboundDecision>[0]["groupHistories"];
|
||||
}) {
|
||||
const groupHistories = params.groupHistories ?? new Map();
|
||||
const decision = resolveIMessageInboundDecision({
|
||||
cfg,
|
||||
cfg: params.cfg,
|
||||
accountId: "default",
|
||||
message,
|
||||
message: params.message,
|
||||
opts: {},
|
||||
messageText: message.text ?? "",
|
||||
bodyText: message.text ?? "",
|
||||
messageText: params.message.text ?? "",
|
||||
bodyText: params.message.text ?? "",
|
||||
allowFrom: ["*"],
|
||||
groupAllowFrom: [],
|
||||
groupPolicy: "open",
|
||||
@@ -70,6 +73,12 @@ function buildDispatchContextPayload(params: { cfg: OpenClawConfig; message: IMe
|
||||
if (decision.kind !== "dispatch") {
|
||||
throw new Error("expected dispatch decision");
|
||||
}
|
||||
return { decision, groupHistories };
|
||||
}
|
||||
|
||||
function buildDispatchContextPayload(params: { cfg: OpenClawConfig; message: IMessagePayload }) {
|
||||
const { cfg, message } = params;
|
||||
const { decision, groupHistories } = resolveDispatchDecision({ cfg, message });
|
||||
|
||||
const { ctxPayload } = buildIMessageInboundContext({
|
||||
cfg,
|
||||
@@ -167,25 +176,7 @@ describe("imessage monitor gating + envelope builders", () => {
|
||||
text: "hello",
|
||||
is_group: false,
|
||||
};
|
||||
const decision = resolveIMessageInboundDecision({
|
||||
cfg,
|
||||
accountId: "default",
|
||||
message,
|
||||
opts: {},
|
||||
messageText: message.text ?? "",
|
||||
bodyText: message.text ?? "",
|
||||
allowFrom: ["*"],
|
||||
groupAllowFrom: [],
|
||||
groupPolicy: "open",
|
||||
dmPolicy: "open",
|
||||
storeAllowFrom: [],
|
||||
historyLimit: 0,
|
||||
groupHistories,
|
||||
});
|
||||
expect(decision.kind).toBe("dispatch");
|
||||
if (decision.kind !== "dispatch") {
|
||||
throw new Error("expected dispatch decision");
|
||||
}
|
||||
const { decision } = resolveDispatchDecision({ cfg, message, groupHistories });
|
||||
expect(decision.isGroup).toBe(true);
|
||||
expect(decision.route.sessionKey).toBe("agent:main:imessage:group:2");
|
||||
});
|
||||
|
||||
@@ -34,6 +34,13 @@ type Registered = {
|
||||
methods: Map<string, unknown>;
|
||||
tools: unknown[];
|
||||
};
|
||||
type RegisterVoiceCall = (api: Record<string, unknown>) => void | Promise<void>;
|
||||
type RegisterCliContext = {
|
||||
program: Command;
|
||||
config: Record<string, unknown>;
|
||||
workspaceDir?: string;
|
||||
logger: typeof noopLogger;
|
||||
};
|
||||
|
||||
function setup(config: Record<string, unknown>): Registered {
|
||||
const methods = new Map<string, unknown>();
|
||||
@@ -59,6 +66,34 @@ function setup(config: Record<string, unknown>): Registered {
|
||||
return { methods, tools };
|
||||
}
|
||||
|
||||
async function registerVoiceCallCli(program: Command) {
|
||||
const { register } = plugin as unknown as {
|
||||
register: RegisterVoiceCall;
|
||||
};
|
||||
await register({
|
||||
id: "voice-call",
|
||||
name: "Voice Call",
|
||||
description: "test",
|
||||
version: "0",
|
||||
source: "test",
|
||||
config: {},
|
||||
pluginConfig: { provider: "mock" },
|
||||
runtime: { tts: { textToSpeechTelephony: vi.fn() } },
|
||||
logger: noopLogger,
|
||||
registerGatewayMethod: () => {},
|
||||
registerTool: () => {},
|
||||
registerCli: (fn: (ctx: RegisterCliContext) => void) =>
|
||||
fn({
|
||||
program,
|
||||
config: {},
|
||||
workspaceDir: undefined,
|
||||
logger: noopLogger,
|
||||
}),
|
||||
registerService: () => {},
|
||||
resolvePath: (p: string) => p,
|
||||
});
|
||||
}
|
||||
|
||||
describe("voice-call plugin", () => {
|
||||
beforeEach(() => {
|
||||
runtimeStub = {
|
||||
@@ -145,9 +180,6 @@ describe("voice-call plugin", () => {
|
||||
});
|
||||
|
||||
it("CLI latency summarizes turn metrics from JSONL", async () => {
|
||||
const { register } = plugin as unknown as {
|
||||
register: (api: Record<string, unknown>) => void | Promise<void>;
|
||||
};
|
||||
const program = new Command();
|
||||
const tmpFile = path.join(os.tmpdir(), `voicecall-latency-${Date.now()}.jsonl`);
|
||||
fs.writeFileSync(
|
||||
@@ -162,35 +194,7 @@ describe("voice-call plugin", () => {
|
||||
const logSpy = vi.spyOn(console, "log").mockImplementation(() => {});
|
||||
|
||||
try {
|
||||
await register({
|
||||
id: "voice-call",
|
||||
name: "Voice Call",
|
||||
description: "test",
|
||||
version: "0",
|
||||
source: "test",
|
||||
config: {},
|
||||
pluginConfig: { provider: "mock" },
|
||||
runtime: { tts: { textToSpeechTelephony: vi.fn() } },
|
||||
logger: noopLogger,
|
||||
registerGatewayMethod: () => {},
|
||||
registerTool: () => {},
|
||||
registerCli: (
|
||||
fn: (ctx: {
|
||||
program: Command;
|
||||
config: Record<string, unknown>;
|
||||
workspaceDir?: string;
|
||||
logger: typeof noopLogger;
|
||||
}) => void,
|
||||
) =>
|
||||
fn({
|
||||
program,
|
||||
config: {},
|
||||
workspaceDir: undefined,
|
||||
logger: noopLogger,
|
||||
}),
|
||||
registerService: () => {},
|
||||
resolvePath: (p: string) => p,
|
||||
});
|
||||
await registerVoiceCallCli(program);
|
||||
|
||||
await program.parseAsync(["voicecall", "latency", "--file", tmpFile, "--last", "10"], {
|
||||
from: "user",
|
||||
@@ -208,40 +212,9 @@ describe("voice-call plugin", () => {
|
||||
});
|
||||
|
||||
it("CLI start prints JSON", async () => {
|
||||
const { register } = plugin as unknown as {
|
||||
register: (api: Record<string, unknown>) => void | Promise<void>;
|
||||
};
|
||||
const program = new Command();
|
||||
const logSpy = vi.spyOn(console, "log").mockImplementation(() => {});
|
||||
await register({
|
||||
id: "voice-call",
|
||||
name: "Voice Call",
|
||||
description: "test",
|
||||
version: "0",
|
||||
source: "test",
|
||||
config: {},
|
||||
pluginConfig: { provider: "mock" },
|
||||
runtime: { tts: { textToSpeechTelephony: vi.fn() } },
|
||||
logger: noopLogger,
|
||||
registerGatewayMethod: () => {},
|
||||
registerTool: () => {},
|
||||
registerCli: (
|
||||
fn: (ctx: {
|
||||
program: Command;
|
||||
config: Record<string, unknown>;
|
||||
workspaceDir?: string;
|
||||
logger: typeof noopLogger;
|
||||
}) => void,
|
||||
) =>
|
||||
fn({
|
||||
program,
|
||||
config: {},
|
||||
workspaceDir: undefined,
|
||||
logger: noopLogger,
|
||||
}),
|
||||
registerService: () => {},
|
||||
resolvePath: (p: string) => p,
|
||||
});
|
||||
await registerVoiceCallCli(program);
|
||||
|
||||
await program.parseAsync(["voicecall", "start", "--to", "+1", "--message", "Hello"], {
|
||||
from: "user",
|
||||
|
||||
Reference in New Issue
Block a user