mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-10 03:02:45 +00:00
test: dedupe shared setup in channel and doctor config tests
This commit is contained in:
@@ -6,7 +6,6 @@ import type { DiscordProbe } from "../../discord/probe.js";
|
|||||||
import type { DiscordTokenResolution } from "../../discord/token.js";
|
import type { DiscordTokenResolution } from "../../discord/token.js";
|
||||||
import type { IMessageProbe } from "../../imessage/probe.js";
|
import type { IMessageProbe } from "../../imessage/probe.js";
|
||||||
import type { LineProbeResult } from "../../line/types.js";
|
import type { LineProbeResult } from "../../line/types.js";
|
||||||
import type { PluginRegistry } from "../../plugins/registry.js";
|
|
||||||
import { setActivePluginRegistry } from "../../plugins/runtime.js";
|
import { setActivePluginRegistry } from "../../plugins/runtime.js";
|
||||||
import type { SignalProbe } from "../../signal/probe.js";
|
import type { SignalProbe } from "../../signal/probe.js";
|
||||||
import type { SlackProbe } from "../../slack/probe.js";
|
import type { SlackProbe } from "../../slack/probe.js";
|
||||||
@@ -118,23 +117,7 @@ describe("channel plugin catalog", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const createRegistry = (channels: PluginRegistry["channels"]): PluginRegistry => ({
|
const emptyRegistry = createTestRegistry([]);
|
||||||
plugins: [],
|
|
||||||
tools: [],
|
|
||||||
hooks: [],
|
|
||||||
typedHooks: [],
|
|
||||||
commands: [],
|
|
||||||
channels,
|
|
||||||
providers: [],
|
|
||||||
gatewayHandlers: {},
|
|
||||||
httpHandlers: [],
|
|
||||||
httpRoutes: [],
|
|
||||||
cliRegistrars: [],
|
|
||||||
services: [],
|
|
||||||
diagnostics: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
const emptyRegistry = createRegistry([]);
|
|
||||||
|
|
||||||
const msteamsOutbound: ChannelOutboundAdapter = {
|
const msteamsOutbound: ChannelOutboundAdapter = {
|
||||||
deliveryMode: "direct",
|
deliveryMode: "direct",
|
||||||
@@ -160,7 +143,7 @@ const msteamsPlugin: ChannelPlugin = {
|
|||||||
outbound: msteamsOutbound,
|
outbound: msteamsOutbound,
|
||||||
};
|
};
|
||||||
|
|
||||||
const registryWithMSTeams = createRegistry([
|
const registryWithMSTeams = createTestRegistry([
|
||||||
{ pluginId: "msteams", plugin: msteamsPlugin, source: "test" },
|
{ pluginId: "msteams", plugin: msteamsPlugin, source: "test" },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,19 @@ async function runDoctorConfigWithInput(params: {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function expectGoogleChatDmAllowFromRepaired(cfg: unknown) {
|
||||||
|
const typed = cfg as {
|
||||||
|
channels: {
|
||||||
|
googlechat: {
|
||||||
|
dm: { allowFrom: string[] };
|
||||||
|
allowFrom?: string[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
expect(typed.channels.googlechat.dm.allowFrom).toEqual(["*"]);
|
||||||
|
expect(typed.channels.googlechat.allowFrom).toBeUndefined();
|
||||||
|
}
|
||||||
|
|
||||||
describe("doctor config flow", () => {
|
describe("doctor config flow", () => {
|
||||||
it("preserves invalid config for doctor repairs", async () => {
|
it("preserves invalid config for doctor repairs", async () => {
|
||||||
const result = await runDoctorConfigWithInput({
|
const result = await runDoctorConfigWithInput({
|
||||||
@@ -361,20 +374,7 @@ describe("doctor config flow", () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const cfg = result.cfg as unknown as {
|
expectGoogleChatDmAllowFromRepaired(result.cfg);
|
||||||
channels: {
|
|
||||||
googlechat: {
|
|
||||||
dm: {
|
|
||||||
policy: string;
|
|
||||||
allowFrom: string[];
|
|
||||||
};
|
|
||||||
allowFrom?: string[];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(cfg.channels.googlechat.dm.allowFrom).toEqual(["*"]);
|
|
||||||
expect(cfg.channels.googlechat.allowFrom).toBeUndefined();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("repairs googlechat account dm.policy open by setting dm.allowFrom on repair", async () => {
|
it("repairs googlechat account dm.policy open by setting dm.allowFrom on repair", async () => {
|
||||||
@@ -430,19 +430,6 @@ describe("doctor config flow", () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const cfg = result.cfg as unknown as {
|
expectGoogleChatDmAllowFromRepaired(result.cfg);
|
||||||
channels: {
|
|
||||||
googlechat: {
|
|
||||||
dm: {
|
|
||||||
policy: string;
|
|
||||||
allowFrom: string[];
|
|
||||||
};
|
|
||||||
allowFrom?: string[];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(cfg.channels.googlechat.dm.allowFrom).toEqual(["*"]);
|
|
||||||
expect(cfg.channels.googlechat.allowFrom).toBeUndefined();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -51,6 +51,26 @@ vi.mock("./daemon-install-helpers.js", () => ({
|
|||||||
|
|
||||||
import { maybeRepairGatewayServiceConfig } from "./doctor-gateway-services.js";
|
import { maybeRepairGatewayServiceConfig } from "./doctor-gateway-services.js";
|
||||||
|
|
||||||
|
function makeDoctorIo() {
|
||||||
|
return { log: vi.fn(), error: vi.fn(), exit: vi.fn() };
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeDoctorPrompts() {
|
||||||
|
return {
|
||||||
|
confirm: vi.fn().mockResolvedValue(true),
|
||||||
|
confirmRepair: vi.fn().mockResolvedValue(true),
|
||||||
|
confirmAggressive: vi.fn().mockResolvedValue(true),
|
||||||
|
confirmSkipInNonInteractive: vi.fn().mockResolvedValue(true),
|
||||||
|
select: vi.fn().mockResolvedValue("node"),
|
||||||
|
shouldRepair: false,
|
||||||
|
shouldForce: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runRepair(cfg: OpenClawConfig) {
|
||||||
|
await maybeRepairGatewayServiceConfig(cfg, "local", makeDoctorIo(), makeDoctorPrompts());
|
||||||
|
}
|
||||||
|
|
||||||
describe("maybeRepairGatewayServiceConfig", () => {
|
describe("maybeRepairGatewayServiceConfig", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
@@ -91,20 +111,7 @@ describe("maybeRepairGatewayServiceConfig", () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
await maybeRepairGatewayServiceConfig(
|
await runRepair(cfg);
|
||||||
cfg,
|
|
||||||
"local",
|
|
||||||
{ log: vi.fn(), error: vi.fn(), exit: vi.fn() },
|
|
||||||
{
|
|
||||||
confirm: vi.fn().mockResolvedValue(true),
|
|
||||||
confirmRepair: vi.fn().mockResolvedValue(true),
|
|
||||||
confirmAggressive: vi.fn().mockResolvedValue(true),
|
|
||||||
confirmSkipInNonInteractive: vi.fn().mockResolvedValue(true),
|
|
||||||
select: vi.fn().mockResolvedValue("node"),
|
|
||||||
shouldRepair: false,
|
|
||||||
shouldForce: false,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(mocks.auditGatewayServiceConfig).toHaveBeenCalledWith(
|
expect(mocks.auditGatewayServiceConfig).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
@@ -164,20 +171,7 @@ describe("maybeRepairGatewayServiceConfig", () => {
|
|||||||
gateway: {},
|
gateway: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
await maybeRepairGatewayServiceConfig(
|
await runRepair(cfg);
|
||||||
cfg,
|
|
||||||
"local",
|
|
||||||
{ log: vi.fn(), error: vi.fn(), exit: vi.fn() },
|
|
||||||
{
|
|
||||||
confirm: vi.fn().mockResolvedValue(true),
|
|
||||||
confirmRepair: vi.fn().mockResolvedValue(true),
|
|
||||||
confirmAggressive: vi.fn().mockResolvedValue(true),
|
|
||||||
confirmSkipInNonInteractive: vi.fn().mockResolvedValue(true),
|
|
||||||
select: vi.fn().mockResolvedValue("node"),
|
|
||||||
shouldRepair: false,
|
|
||||||
shouldForce: false,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(mocks.auditGatewayServiceConfig).toHaveBeenCalledWith(
|
expect(mocks.auditGatewayServiceConfig).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||||
import type { ChannelPlugin } from "../channels/plugins/types.js";
|
import type { ChannelPlugin } from "../channels/plugins/types.js";
|
||||||
import type { PluginRegistry } from "../plugins/registry.js";
|
|
||||||
import { setActivePluginRegistry } from "../plugins/runtime.js";
|
import { setActivePluginRegistry } from "../plugins/runtime.js";
|
||||||
|
import { createTestRegistry } from "../test-utils/channel-plugins.js";
|
||||||
import { resolveChannelCapabilities } from "./channel-capabilities.js";
|
import { resolveChannelCapabilities } from "./channel-capabilities.js";
|
||||||
import type { OpenClawConfig } from "./config.js";
|
import type { OpenClawConfig } from "./config.js";
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ describe("resolveChannelCapabilities", () => {
|
|||||||
|
|
||||||
it("supports msteams capabilities", () => {
|
it("supports msteams capabilities", () => {
|
||||||
setActivePluginRegistry(
|
setActivePluginRegistry(
|
||||||
createRegistry([
|
createTestRegistry([
|
||||||
{
|
{
|
||||||
pluginId: "msteams",
|
pluginId: "msteams",
|
||||||
source: "test",
|
source: "test",
|
||||||
@@ -127,22 +127,6 @@ describe("resolveChannelCapabilities", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const createRegistry = (channels: PluginRegistry["channels"]): PluginRegistry => ({
|
|
||||||
plugins: [],
|
|
||||||
tools: [],
|
|
||||||
hooks: [],
|
|
||||||
typedHooks: [],
|
|
||||||
commands: [],
|
|
||||||
channels,
|
|
||||||
providers: [],
|
|
||||||
gatewayHandlers: {},
|
|
||||||
httpHandlers: [],
|
|
||||||
httpRoutes: [],
|
|
||||||
cliRegistrars: [],
|
|
||||||
services: [],
|
|
||||||
diagnostics: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
const createStubPlugin = (id: string): ChannelPlugin => ({
|
const createStubPlugin = (id: string): ChannelPlugin => ({
|
||||||
id,
|
id,
|
||||||
meta: {
|
meta: {
|
||||||
@@ -159,7 +143,7 @@ const createStubPlugin = (id: string): ChannelPlugin => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const baseRegistry = createRegistry([
|
const baseRegistry = createTestRegistry([
|
||||||
{ pluginId: "telegram", source: "test", plugin: createStubPlugin("telegram") },
|
{ pluginId: "telegram", source: "test", plugin: createStubPlugin("telegram") },
|
||||||
{ pluginId: "slack", source: "test", plugin: createStubPlugin("slack") },
|
{ pluginId: "slack", source: "test", plugin: createStubPlugin("slack") },
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -15,6 +15,24 @@ installCronTestHooks({
|
|||||||
baseTimeIso: "2026-02-06T17:00:00.000Z",
|
baseTimeIso: "2026-02-06T17:00:00.000Z",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function createStartedCron(storePath: string) {
|
||||||
|
const cron = new CronService({
|
||||||
|
storePath,
|
||||||
|
cronEnabled: true,
|
||||||
|
log: noopLogger,
|
||||||
|
enqueueSystemEvent: vi.fn(),
|
||||||
|
requestHeartbeatNow: vi.fn(),
|
||||||
|
runIsolatedAgentJob: vi.fn(async () => ({ status: "ok" as const, summary: "ok" })),
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
cron,
|
||||||
|
start: async () => {
|
||||||
|
await cron.start();
|
||||||
|
return cron;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
describe("CronService store migrations", () => {
|
describe("CronService store migrations", () => {
|
||||||
it("migrates legacy top-level agentTurn fields and initializes missing state", async () => {
|
it("migrates legacy top-level agentTurn fields and initializes missing state", async () => {
|
||||||
const store = await makeStorePath();
|
const store = await makeStorePath();
|
||||||
@@ -52,16 +70,7 @@ describe("CronService store migrations", () => {
|
|||||||
"utf-8",
|
"utf-8",
|
||||||
);
|
);
|
||||||
|
|
||||||
const cron = new CronService({
|
const cron = await createStartedCron(store.storePath).start();
|
||||||
storePath: store.storePath,
|
|
||||||
cronEnabled: true,
|
|
||||||
log: noopLogger,
|
|
||||||
enqueueSystemEvent: vi.fn(),
|
|
||||||
requestHeartbeatNow: vi.fn(),
|
|
||||||
runIsolatedAgentJob: vi.fn(async () => ({ status: "ok" as const, summary: "ok" })),
|
|
||||||
});
|
|
||||||
|
|
||||||
await cron.start();
|
|
||||||
|
|
||||||
const status = await cron.status();
|
const status = await cron.status();
|
||||||
expect(status.enabled).toBe(true);
|
expect(status.enabled).toBe(true);
|
||||||
@@ -132,16 +141,7 @@ describe("CronService store migrations", () => {
|
|||||||
"utf-8",
|
"utf-8",
|
||||||
);
|
);
|
||||||
|
|
||||||
const cron = new CronService({
|
const cron = await createStartedCron(store.storePath).start();
|
||||||
storePath: store.storePath,
|
|
||||||
cronEnabled: true,
|
|
||||||
log: noopLogger,
|
|
||||||
enqueueSystemEvent: vi.fn(),
|
|
||||||
requestHeartbeatNow: vi.fn(),
|
|
||||||
runIsolatedAgentJob: vi.fn(async () => ({ status: "ok" as const, summary: "ok" })),
|
|
||||||
});
|
|
||||||
|
|
||||||
await cron.start();
|
|
||||||
|
|
||||||
const jobs = await cron.list({ includeDisabled: true });
|
const jobs = await cron.list({ includeDisabled: true });
|
||||||
const job = jobs.find((entry) => entry.id === "legacy-agentturn-no-timeout");
|
const job = jobs.find((entry) => entry.id === "legacy-agentturn-no-timeout");
|
||||||
|
|||||||
Reference in New Issue
Block a user