mirror of https://github.com/openclaw/openclaw.git
test: tighten fetch and channel summary coverage
This commit is contained in:
parent
0e8672af87
commit
060f3e5f9a
|
|
@ -124,6 +124,51 @@ function makeTelegramSummaryPlugin(params: {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function makeSignalSummaryPlugin(params: { enabled: boolean; configured: boolean }): ChannelPlugin {
|
||||||
|
return {
|
||||||
|
id: "signal",
|
||||||
|
meta: {
|
||||||
|
id: "signal",
|
||||||
|
label: "Signal",
|
||||||
|
selectionLabel: "Signal",
|
||||||
|
docsPath: "/channels/signal",
|
||||||
|
blurb: "test",
|
||||||
|
},
|
||||||
|
capabilities: { chatTypes: ["direct"] },
|
||||||
|
config: {
|
||||||
|
listAccountIds: () => ["desktop"],
|
||||||
|
defaultAccountId: () => "desktop",
|
||||||
|
inspectAccount: () => ({
|
||||||
|
accountId: "desktop",
|
||||||
|
name: "Desktop",
|
||||||
|
enabled: params.enabled,
|
||||||
|
configured: params.configured,
|
||||||
|
appTokenSource: "env",
|
||||||
|
baseUrl: "https://signal.example.test",
|
||||||
|
port: 31337,
|
||||||
|
cliPath: "/usr/local/bin/signal-cli",
|
||||||
|
dbPath: "/tmp/signal.db",
|
||||||
|
}),
|
||||||
|
resolveAccount: () => ({
|
||||||
|
accountId: "desktop",
|
||||||
|
name: "Desktop",
|
||||||
|
enabled: params.enabled,
|
||||||
|
configured: params.configured,
|
||||||
|
appTokenSource: "env",
|
||||||
|
baseUrl: "https://signal.example.test",
|
||||||
|
port: 31337,
|
||||||
|
cliPath: "/usr/local/bin/signal-cli",
|
||||||
|
dbPath: "/tmp/signal.db",
|
||||||
|
}),
|
||||||
|
isConfigured: (account) => Boolean((account as { configured?: boolean }).configured),
|
||||||
|
isEnabled: (account) => Boolean((account as { enabled?: boolean }).enabled),
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
listActions: () => ["send"],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
describe("buildChannelSummary", () => {
|
describe("buildChannelSummary", () => {
|
||||||
it("preserves Slack HTTP signing-secret unavailable state from source config", async () => {
|
it("preserves Slack HTTP signing-secret unavailable state from source config", async () => {
|
||||||
vi.mocked(listChannelPlugins).mockReturnValue([makeSlackHttpSummaryPlugin()]);
|
vi.mocked(listChannelPlugins).mockReturnValue([makeSlackHttpSummaryPlugin()]);
|
||||||
|
|
@ -172,4 +217,38 @@ describe("buildChannelSummary", () => {
|
||||||
expect(lines).toContain("Telegram: linked +15551234567 auth 5m ago");
|
expect(lines).toContain("Telegram: linked +15551234567 auth 5m ago");
|
||||||
expect(lines).toContain(" - primary (Main Bot) (dm:mutuals, token:env, allow:alice,bob)");
|
expect(lines).toContain(" - primary (Main Bot) (dm:mutuals, token:env, allow:alice,bob)");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("shows not-linked status when linked metadata is explicitly false", async () => {
|
||||||
|
vi.mocked(listChannelPlugins).mockReturnValue([
|
||||||
|
makeTelegramSummaryPlugin({
|
||||||
|
enabled: true,
|
||||||
|
configured: true,
|
||||||
|
linked: false,
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const lines = await buildChannelSummary({ channels: {} } as never, {
|
||||||
|
colorize: false,
|
||||||
|
includeAllowFrom: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(lines).toContain("Telegram: not linked +15551234567");
|
||||||
|
expect(lines).toContain(" - primary (Main Bot) (dm:mutuals, token:env)");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders non-slack account detail fields for configured accounts", async () => {
|
||||||
|
vi.mocked(listChannelPlugins).mockReturnValue([
|
||||||
|
makeSignalSummaryPlugin({ enabled: false, configured: true }),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const lines = await buildChannelSummary({ channels: {} } as never, {
|
||||||
|
colorize: false,
|
||||||
|
includeAllowFrom: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(lines).toEqual([
|
||||||
|
"Signal: disabled",
|
||||||
|
" - desktop (Desktop) (disabled, app:env, https://signal.example.test, port:31337, cli:/usr/local/bin/signal-cli, db:/tmp/signal.db)",
|
||||||
|
]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -223,6 +223,48 @@ describe("wrapFetchWithAbortSignal", () => {
|
||||||
expect(seenSignal).toBe(fakeSignal);
|
expect(seenSignal).toBe(fakeSignal);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("passes through native AbortSignal instances unchanged", async () => {
|
||||||
|
let seenSignal: AbortSignal | undefined;
|
||||||
|
const fetchImpl = withFetchPreconnect(
|
||||||
|
vi.fn(async (_input: RequestInfo | URL, init?: RequestInit) => {
|
||||||
|
seenSignal = init?.signal as AbortSignal | undefined;
|
||||||
|
return {} as Response;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const wrapped = wrapFetchWithAbortSignal(fetchImpl);
|
||||||
|
const controller = new AbortController();
|
||||||
|
|
||||||
|
await wrapped("https://example.com", { signal: controller.signal });
|
||||||
|
|
||||||
|
expect(seenSignal).toBe(controller.signal);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("passes through foreign signals unchanged when AbortController is unavailable", async () => {
|
||||||
|
let seenSignal: AbortSignal | undefined;
|
||||||
|
const fetchImpl = withFetchPreconnect(
|
||||||
|
vi.fn(async (_input: RequestInfo | URL, init?: RequestInit) => {
|
||||||
|
seenSignal = init?.signal as AbortSignal | undefined;
|
||||||
|
return {} as Response;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const wrapped = wrapFetchWithAbortSignal(fetchImpl);
|
||||||
|
const fakeSignal = {
|
||||||
|
aborted: false,
|
||||||
|
addEventListener: vi.fn(),
|
||||||
|
removeEventListener: vi.fn(),
|
||||||
|
} as unknown as AbortSignal;
|
||||||
|
const previousAbortController = globalThis.AbortController;
|
||||||
|
vi.stubGlobal("AbortController", undefined);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await wrapped("https://example.com", { signal: fakeSignal });
|
||||||
|
} finally {
|
||||||
|
vi.stubGlobal("AbortController", previousAbortController);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(seenSignal).toBe(fakeSignal);
|
||||||
|
});
|
||||||
|
|
||||||
it("returns the same function when called with an already wrapped fetch", () => {
|
it("returns the same function when called with an already wrapped fetch", () => {
|
||||||
const fetchImpl = withFetchPreconnect(vi.fn(async () => ({ ok: true }) as Response));
|
const fetchImpl = withFetchPreconnect(vi.fn(async () => ({ ok: true }) as Response));
|
||||||
const wrapped = wrapFetchWithAbortSignal(fetchImpl);
|
const wrapped = wrapFetchWithAbortSignal(fetchImpl);
|
||||||
|
|
@ -249,6 +291,15 @@ describe("wrapFetchWithAbortSignal", () => {
|
||||||
expect(preconnectSpy).toHaveBeenCalledOnce();
|
expect(preconnectSpy).toHaveBeenCalledOnce();
|
||||||
expect(seenThis).toBe(fetchImpl);
|
expect(seenThis).toBe(fetchImpl);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("exposes a no-op preconnect when the source fetch has none", () => {
|
||||||
|
const fetchImpl = vi.fn(async () => ({ ok: true }) as Response) as typeof fetch;
|
||||||
|
const wrapped = wrapFetchWithAbortSignal(fetchImpl) as typeof fetch & {
|
||||||
|
preconnect: (url: string, init?: { credentials?: RequestCredentials }) => unknown;
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(() => wrapped.preconnect("https://example.com")).not.toThrow();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("resolveFetch", () => {
|
describe("resolveFetch", () => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue