mirror of https://github.com/openclaw/openclaw.git
235 lines
7.3 KiB
TypeScript
235 lines
7.3 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
import {
|
|
applyStatusScanDefaults,
|
|
createStatusMemorySearchConfig,
|
|
createStatusMemorySearchManager,
|
|
createStatusScanSharedMocks,
|
|
createStatusScanConfig,
|
|
createStatusSummary,
|
|
loadStatusScanModuleForTest,
|
|
withTemporaryEnv,
|
|
} from "./status.scan.test-helpers.js";
|
|
|
|
const mocks = {
|
|
...createStatusScanSharedMocks("status-scan"),
|
|
buildChannelsTable: vi.fn(),
|
|
callGateway: vi.fn(),
|
|
};
|
|
|
|
let originalForceStderr: boolean;
|
|
let loggingStateRef: typeof import("../logging/state.js").loggingState;
|
|
let scanStatus: typeof import("./status.scan.js").scanStatus;
|
|
|
|
beforeEach(async () => {
|
|
vi.clearAllMocks();
|
|
configureScanStatus();
|
|
({ scanStatus } = await loadStatusScanModuleForTest(mocks));
|
|
({ loggingState: loggingStateRef } = await import("../logging/state.js"));
|
|
originalForceStderr = loggingStateRef.forceConsoleToStderr;
|
|
loggingStateRef.forceConsoleToStderr = false;
|
|
});
|
|
|
|
afterEach(() => {
|
|
loggingStateRef.forceConsoleToStderr = originalForceStderr;
|
|
});
|
|
|
|
function configureScanStatus(
|
|
options: {
|
|
hasConfiguredChannels?: boolean;
|
|
sourceConfig?: ReturnType<typeof createStatusScanConfig>;
|
|
resolvedConfig?: ReturnType<typeof createStatusScanConfig>;
|
|
summary?: ReturnType<typeof createStatusSummary>;
|
|
update?: false;
|
|
gatewayProbe?: false;
|
|
memoryConfigured?: boolean;
|
|
} = {},
|
|
) {
|
|
const sourceConfig = options.memoryConfigured
|
|
? createStatusMemorySearchConfig()
|
|
: (options.sourceConfig ?? createStatusScanConfig());
|
|
const resolvedConfig = options.memoryConfigured
|
|
? createStatusMemorySearchConfig()
|
|
: (options.resolvedConfig ?? sourceConfig);
|
|
|
|
applyStatusScanDefaults(mocks, {
|
|
hasConfiguredChannels: options.hasConfiguredChannels,
|
|
sourceConfig,
|
|
resolvedConfig,
|
|
summary: options.summary,
|
|
update: options.update,
|
|
gatewayProbe: options.gatewayProbe,
|
|
...(options.memoryConfigured ? { memoryManager: createStatusMemorySearchManager() } : {}),
|
|
});
|
|
mocks.buildChannelsTable.mockResolvedValue({
|
|
rows: [],
|
|
details: [],
|
|
});
|
|
mocks.callGateway.mockResolvedValue(null);
|
|
}
|
|
|
|
describe("scanStatus", () => {
|
|
it("passes sourceConfig into buildChannelsTable for summary-mode status output", async () => {
|
|
configureScanStatus({
|
|
sourceConfig: createStatusScanConfig({
|
|
marker: "source",
|
|
plugins: { enabled: false },
|
|
}),
|
|
resolvedConfig: createStatusScanConfig({
|
|
marker: "resolved",
|
|
plugins: { enabled: false },
|
|
}),
|
|
summary: createStatusSummary({ linkChannel: { linked: false } }),
|
|
});
|
|
|
|
await scanStatus({ json: false }, {} as never);
|
|
|
|
expect(mocks.buildChannelsTable).toHaveBeenCalledWith(
|
|
expect.objectContaining({ marker: "resolved" }),
|
|
expect.objectContaining({
|
|
sourceConfig: expect.objectContaining({ marker: "source" }),
|
|
}),
|
|
);
|
|
});
|
|
|
|
it("skips channel plugin preload for status --json with no channel config", async () => {
|
|
configureScanStatus({
|
|
sourceConfig: createStatusScanConfig({
|
|
plugins: { enabled: false },
|
|
}),
|
|
resolvedConfig: createStatusScanConfig({
|
|
plugins: { enabled: false },
|
|
}),
|
|
});
|
|
|
|
await scanStatus({ json: true }, {} as never);
|
|
|
|
expect(mocks.ensurePluginRegistryLoaded).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("skips plugin compatibility loading for status --json when the config file is missing", async () => {
|
|
configureScanStatus({
|
|
sourceConfig: createStatusScanConfig({
|
|
plugins: { enabled: true },
|
|
}),
|
|
resolvedConfig: createStatusScanConfig({
|
|
plugins: { enabled: true },
|
|
}),
|
|
});
|
|
|
|
await scanStatus({ json: true }, {} as never);
|
|
|
|
expect(mocks.buildPluginCompatibilityNotices).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("skips plugin compatibility loading for status --json even with configured channels", async () => {
|
|
configureScanStatus({
|
|
hasConfiguredChannels: true,
|
|
sourceConfig: createStatusScanConfig({
|
|
channels: { discord: {} },
|
|
}),
|
|
resolvedConfig: createStatusScanConfig({
|
|
channels: { discord: {} },
|
|
}),
|
|
});
|
|
|
|
await scanStatus({ json: true }, {} as never);
|
|
|
|
expect(mocks.buildPluginCompatibilityNotices).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("skips gateway and update probes on cold-start status paths", async () => {
|
|
configureScanStatus({
|
|
sourceConfig: createStatusScanConfig({
|
|
plugins: { enabled: false },
|
|
}),
|
|
resolvedConfig: createStatusScanConfig({
|
|
plugins: { enabled: false },
|
|
}),
|
|
update: false,
|
|
gatewayProbe: false,
|
|
});
|
|
|
|
await scanStatus({ json: true }, {} as never);
|
|
await scanStatus({ json: false }, {} as never);
|
|
|
|
expect(mocks.getUpdateCheckResult).not.toHaveBeenCalled();
|
|
expect(mocks.probeGateway).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("skips memory backend inspection for default memory-core with no existing store", async () => {
|
|
configureScanStatus();
|
|
|
|
await scanStatus({ json: true }, {} as never);
|
|
|
|
expect(mocks.getMemorySearchManager).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("inspects memory backend when memory search is explicitly configured", async () => {
|
|
configureScanStatus({ memoryConfigured: true });
|
|
|
|
await scanStatus({ json: true }, {} as never);
|
|
|
|
expect(mocks.getMemorySearchManager).toHaveBeenCalledWith({
|
|
cfg: expect.objectContaining({
|
|
agents: expect.objectContaining({
|
|
defaults: expect.objectContaining({
|
|
memorySearch: expect.any(Object),
|
|
}),
|
|
}),
|
|
}),
|
|
agentId: "main",
|
|
purpose: "status",
|
|
});
|
|
});
|
|
|
|
it("preloads configured channel plugins for status --json when channel config exists", async () => {
|
|
configureScanStatus({
|
|
hasConfiguredChannels: true,
|
|
sourceConfig: createStatusScanConfig({
|
|
plugins: { enabled: false },
|
|
channels: { telegram: { enabled: false } },
|
|
}),
|
|
resolvedConfig: createStatusScanConfig({
|
|
plugins: { enabled: false },
|
|
channels: { telegram: { enabled: false } },
|
|
}),
|
|
summary: createStatusSummary({ linkChannel: { linked: false } }),
|
|
});
|
|
|
|
await scanStatus({ json: true }, {} as never);
|
|
|
|
expect(mocks.ensurePluginRegistryLoaded).toHaveBeenCalledWith({
|
|
scope: "configured-channels",
|
|
});
|
|
// Verify plugin logs were routed to stderr during loading and restored after
|
|
expect(loggingStateRef.forceConsoleToStderr).toBe(false);
|
|
expect(mocks.probeGateway).toHaveBeenCalledWith(
|
|
expect.objectContaining({ detailLevel: "presence" }),
|
|
);
|
|
expect(mocks.callGateway).not.toHaveBeenCalledWith(
|
|
expect.objectContaining({ method: "channels.status" }),
|
|
);
|
|
});
|
|
|
|
it("preloads configured channel plugins for status --json when channel auth is env-only", async () => {
|
|
configureScanStatus({
|
|
hasConfiguredChannels: true,
|
|
sourceConfig: createStatusScanConfig({
|
|
plugins: { enabled: false },
|
|
}),
|
|
resolvedConfig: createStatusScanConfig({
|
|
plugins: { enabled: false },
|
|
}),
|
|
summary: createStatusSummary({ linkChannel: { linked: false } }),
|
|
});
|
|
|
|
await withTemporaryEnv({ MATRIX_ACCESS_TOKEN: "token" }, async () => {
|
|
await scanStatus({ json: true }, {} as never);
|
|
});
|
|
|
|
expect(mocks.ensurePluginRegistryLoaded).toHaveBeenCalledWith({
|
|
scope: "configured-channels",
|
|
});
|
|
});
|
|
});
|