import { beforeEach, describe, expect, it, vi } from "vitest" ;
import type { GatewayRequestHandlerOptions } from "./types.js" ;
const mocks = vi.hoisted(() => ({
loadConfig: vi.fn(() => ({})),
applyPluginAutoEnable: vi.fn(),
listChannelPlugins: vi.fn(),
buildChannelUiCatalog: vi.fn(),
buildChannelAccountSnapshot: vi.fn(),
getChannelActivity: vi.fn(),
}));
vi.mock("../../config/config.js" , () => ({
loadConfig: mocks.loadConfig,
readConfigFileSnapshot: vi.fn(async () => ({
config: {},
path: "openclaw.config.json" ,
raw: "{}" ,
})),
}));
vi.mock("../../config/plugin-auto-enable.js" , () => ({
applyPluginAutoEnable: mocks.applyPluginAutoEnable,
}));
vi.mock("../../channels/plugins/index.js" , () => ({
listChannelPlugins: mocks.listChannelPlugins,
getLoadedChannelPlugin: vi.fn(),
getChannelPlugin: vi.fn(),
normalizeChannelId: (value: string) => value,
}));
vi.mock("../../channels/plugins/catalog.js" , () => ({
buildChannelUiCatalog: mocks.buildChannelUiCatalog,
}));
vi.mock("../../channels/plugins/status.js" , () => ({
buildChannelAccountSnapshot: mocks.buildChannelAccountSnapshot,
}));
vi.mock("../../infra/channel-activity.js" , () => ({
getChannelActivity: mocks.getChannelActivity,
}));
import { channelsHandlers } from "./channels.js" ;
function createOptions(
params: Record<string, unknown>,
overrides?: Partial<GatewayRequestHandlerOptions>,
): GatewayRequestHandlerOptions {
return {
req: { type: "req" , id: "req-1" , method: "channels.status" , params },
params,
client: null ,
isWebchatConnect: () => false ,
respond: vi.fn(),
context: {
getRuntimeSnapshot: () => ({
channels: {},
channelAccounts: {},
}),
},
...overrides,
} as unknown as GatewayRequestHandlerOptions;
}
describe("channelsHandlers channels.status" , () => {
beforeEach(() => {
vi.clearAllMocks();
mocks.loadConfig.mockReturnValue({});
mocks.applyPluginAutoEnable.mockImplementation(({ config }) => ({ config, changes: [] }));
mocks.buildChannelUiCatalog.mockReturnValue({
order: ["whatsapp" ],
labels: { whatsapp: "WhatsApp" },
detailLabels: { whatsapp: "WhatsApp" },
systemImages: { whatsapp: undefined },
entries: { whatsapp: { id: "whatsapp" } },
});
mocks.buildChannelAccountSnapshot.mockResolvedValue({
accountId: "default" ,
configured: true ,
});
mocks.getChannelActivity.mockReturnValue({
inboundAt: null ,
outboundAt: null ,
});
mocks.listChannelPlugins.mockReturnValue([
{
id: "whatsapp" ,
config: {
listAccountIds: () => ["default" ],
resolveAccount: () => ({}),
isEnabled: () => true ,
isConfigured: async (_account: unknown, cfg: { autoEnabled?: boolean }) =>
Boolean (cfg.autoEnabled),
},
},
]);
});
it("uses the auto-enabled config snapshot for channel account state" , async () => {
const autoEnabledConfig = { autoEnabled: true };
mocks.applyPluginAutoEnable.mockReturnValue({ config: autoEnabledConfig, changes: [] });
const respond = vi.fn();
const opts = createOptions(
{ probe: false , timeoutMs: 2000 },
{
respond,
},
);
await channelsHandlers["channels.status" ](opts);
expect(mocks.applyPluginAutoEnable).toHaveBeenCalledWith({
config: {},
env: process.env,
});
expect(mocks.buildChannelAccountSnapshot).toHaveBeenCalledWith(
expect.objectContaining({
cfg: autoEnabledConfig,
accountId: "default" ,
}),
);
expect(respond).toHaveBeenCalledWith(
true ,
expect.objectContaining({
channels: {
whatsapp: expect.objectContaining({
configured: true ,
}),
},
}),
undefined,
);
});
it("caps probe timeout before passing it to channel plugins" , async () => {
const autoEnabledConfig = { autoEnabled: true };
const probeAccount = vi.fn(async () => ({ ok: true }));
mocks.applyPluginAutoEnable.mockReturnValue({ config: autoEnabledConfig, changes: [] });
mocks.listChannelPlugins.mockReturnValue([
{
id: "whatsapp" ,
config: {
listAccountIds: () => ["default" ],
resolveAccount: () => ({}),
isEnabled: () => true ,
isConfigured: async () => true ,
},
status: {
probeAccount,
},
},
]);
await channelsHandlers["channels.status" ](createOptions({ probe: true , timeoutMs: 999 _999 }));
expect(probeAccount).toHaveBeenCalledWith(
expect.objectContaining({
timeoutMs: 30 _000 ,
cfg: autoEnabledConfig,
}),
);
});
});
Messung V0.5 in Prozent C=95 H=91 G=92
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-06-05)
¤
*© Formatika GbR, Deutschland