mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 11:30:43 +00:00
test: mock channels status command seam
This commit is contained in:
@@ -4,22 +4,37 @@ import { channelsStatusCommand } from "./channels/status.js";
|
||||
|
||||
const resolveDefaultAccountId = () => DEFAULT_ACCOUNT_ID;
|
||||
|
||||
const callGateway = vi.fn();
|
||||
const resolveCommandSecretRefsViaGateway = vi.fn();
|
||||
const requireValidConfigSnapshot = vi.fn();
|
||||
const listChannelPlugins = vi.fn();
|
||||
const withProgress = vi.fn(async (_opts: unknown, run: () => Promise<unknown>) => await run());
|
||||
const mocks = vi.hoisted(() => ({
|
||||
callGateway: vi.fn(),
|
||||
resolveCommandConfigWithSecrets: vi.fn(),
|
||||
readConfigFileSnapshot: vi.fn(async () => ({ path: "/tmp/openclaw.json" })),
|
||||
requireValidConfigSnapshot: vi.fn(),
|
||||
listChannelPlugins: vi.fn(),
|
||||
withProgress: vi.fn(async (_opts: unknown, run: () => Promise<unknown>) => await run()),
|
||||
}));
|
||||
|
||||
vi.mock("../gateway/call.js", () => ({
|
||||
callGateway: (opts: unknown) => callGateway(opts),
|
||||
callGateway: (opts: unknown) => mocks.callGateway(opts),
|
||||
}));
|
||||
|
||||
vi.mock("../cli/command-secret-gateway.js", () => ({
|
||||
resolveCommandSecretRefsViaGateway: (opts: unknown) => resolveCommandSecretRefsViaGateway(opts),
|
||||
vi.mock("../cli/command-config-resolution.js", () => ({
|
||||
resolveCommandConfigWithSecrets: async (opts: {
|
||||
runtime?: { log: (message: string) => void };
|
||||
}) => {
|
||||
const result = await mocks.resolveCommandConfigWithSecrets(opts);
|
||||
for (const entry of result?.diagnostics ?? []) {
|
||||
opts.runtime?.log(`[secrets] ${entry}`);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("./shared.js", () => ({
|
||||
requireValidConfigSnapshot: (runtime: unknown) => requireValidConfigSnapshot(runtime),
|
||||
vi.mock("../config/config.js", () => ({
|
||||
readConfigFileSnapshot: () => mocks.readConfigFileSnapshot(),
|
||||
}));
|
||||
|
||||
vi.mock("./channels/shared.js", () => ({
|
||||
requireValidConfigSnapshot: (runtime: unknown) => mocks.requireValidConfigSnapshot(runtime),
|
||||
formatChannelAccountLabel: ({
|
||||
channel,
|
||||
accountId,
|
||||
@@ -31,13 +46,13 @@ vi.mock("./shared.js", () => ({
|
||||
}));
|
||||
|
||||
vi.mock("../channels/plugins/index.js", () => ({
|
||||
listChannelPlugins: () => listChannelPlugins(),
|
||||
listChannelPlugins: () => mocks.listChannelPlugins(),
|
||||
getChannelPlugin: (channel: string) =>
|
||||
(listChannelPlugins() as Array<{ id: string }>).find((plugin) => plugin.id === channel),
|
||||
(mocks.listChannelPlugins() as Array<{ id: string }>).find((plugin) => plugin.id === channel),
|
||||
}));
|
||||
|
||||
vi.mock("../cli/progress.js", () => ({
|
||||
withProgress: (opts: unknown, run: () => Promise<unknown>) => withProgress(opts, run),
|
||||
withProgress: (opts: unknown, run: () => Promise<unknown>) => mocks.withProgress(opts, run),
|
||||
}));
|
||||
|
||||
function createTokenOnlyPlugin() {
|
||||
@@ -112,31 +127,31 @@ function createRuntimeCapture() {
|
||||
|
||||
describe("channelsStatusCommand SecretRef fallback flow", () => {
|
||||
beforeEach(() => {
|
||||
callGateway.mockReset();
|
||||
resolveCommandSecretRefsViaGateway.mockReset();
|
||||
requireValidConfigSnapshot.mockReset();
|
||||
listChannelPlugins.mockReset();
|
||||
withProgress.mockClear();
|
||||
listChannelPlugins.mockReturnValue([createTokenOnlyPlugin()]);
|
||||
mocks.callGateway.mockReset();
|
||||
mocks.resolveCommandConfigWithSecrets.mockReset();
|
||||
mocks.readConfigFileSnapshot.mockClear();
|
||||
mocks.requireValidConfigSnapshot.mockReset();
|
||||
mocks.listChannelPlugins.mockReset();
|
||||
mocks.withProgress.mockClear();
|
||||
mocks.listChannelPlugins.mockReturnValue([createTokenOnlyPlugin()]);
|
||||
});
|
||||
|
||||
it("keeps read-only fallback output when SecretRefs are unresolved", async () => {
|
||||
callGateway.mockRejectedValue(new Error("gateway closed"));
|
||||
requireValidConfigSnapshot.mockResolvedValue({ secretResolved: false, channels: {} });
|
||||
resolveCommandSecretRefsViaGateway.mockResolvedValue({
|
||||
mocks.callGateway.mockRejectedValue(new Error("gateway closed"));
|
||||
mocks.requireValidConfigSnapshot.mockResolvedValue({ secretResolved: false, channels: {} });
|
||||
mocks.resolveCommandConfigWithSecrets.mockResolvedValue({
|
||||
resolvedConfig: { secretResolved: false, channels: {} },
|
||||
effectiveConfig: { secretResolved: false, channels: {} },
|
||||
diagnostics: [
|
||||
"channels status: channels.discord.token is unavailable in this command path; continuing with degraded read-only config.",
|
||||
],
|
||||
targetStatesByPath: {},
|
||||
hadUnresolvedTargets: true,
|
||||
});
|
||||
const { runtime, logs, errors } = createRuntimeCapture();
|
||||
|
||||
await channelsStatusCommand({ probe: false }, runtime as never);
|
||||
|
||||
expect(errors.some((line) => line.includes("Gateway not reachable"))).toBe(true);
|
||||
expect(resolveCommandSecretRefsViaGateway).toHaveBeenCalledWith(
|
||||
expect(mocks.resolveCommandConfigWithSecrets).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
commandName: "channels status",
|
||||
mode: "read_only_status",
|
||||
@@ -153,13 +168,12 @@ describe("channelsStatusCommand SecretRef fallback flow", () => {
|
||||
});
|
||||
|
||||
it("prefers resolved snapshots when command-local SecretRef resolution succeeds", async () => {
|
||||
callGateway.mockRejectedValue(new Error("gateway closed"));
|
||||
requireValidConfigSnapshot.mockResolvedValue({ secretResolved: false, channels: {} });
|
||||
resolveCommandSecretRefsViaGateway.mockResolvedValue({
|
||||
mocks.callGateway.mockRejectedValue(new Error("gateway closed"));
|
||||
mocks.requireValidConfigSnapshot.mockResolvedValue({ secretResolved: false, channels: {} });
|
||||
mocks.resolveCommandConfigWithSecrets.mockResolvedValue({
|
||||
resolvedConfig: { secretResolved: true, channels: {} },
|
||||
effectiveConfig: { secretResolved: true, channels: {} },
|
||||
diagnostics: [],
|
||||
targetStatesByPath: {},
|
||||
hadUnresolvedTargets: false,
|
||||
});
|
||||
const { runtime, logs } = createRuntimeCapture();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user