test: collapse telegram transport and status suites

This commit is contained in:
Peter Steinberger
2026-03-25 11:22:26 +00:00
parent 12082f47bd
commit 52bec1612c
4 changed files with 139 additions and 142 deletions

View File

@@ -1,5 +1,5 @@
import { createRequire } from "node:module";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { fetchTelegramChatId } from "./api-fetch.js";
const require = createRequire(import.meta.url);
@@ -10,6 +10,31 @@ const { kHttpsProxyAgent, kNoProxyAgent } = require("undici/lib/core/symbols.js"
kHttpsProxyAgent: symbol;
kNoProxyAgent: symbol;
};
const proxyMocks = vi.hoisted(() => {
const undiciFetch = vi.fn();
const proxyAgentSpy = vi.fn();
const setGlobalDispatcher = vi.fn();
class ProxyAgent {
static lastCreated: ProxyAgent | undefined;
proxyUrl: string;
constructor(proxyUrl: string) {
this.proxyUrl = proxyUrl;
ProxyAgent.lastCreated = this;
proxyAgentSpy(proxyUrl);
}
}
return {
ProxyAgent,
undiciFetch,
proxyAgentSpy,
setGlobalDispatcher,
getLastAgent: () => ProxyAgent.lastCreated,
};
});
let getProxyUrlFromFetch: typeof import("./proxy.js").getProxyUrlFromFetch;
let makeProxyFetch: typeof import("./proxy.js").makeProxyFetch;
function getOwnSymbolValue(
target: Record<PropertyKey, unknown>,
@@ -136,3 +161,40 @@ describe("undici env proxy semantics", () => {
);
});
});
describe("makeProxyFetch", () => {
beforeEach(async () => {
vi.resetModules();
proxyMocks.undiciFetch.mockReset();
proxyMocks.proxyAgentSpy.mockClear();
proxyMocks.setGlobalDispatcher.mockClear();
vi.doMock("undici", () => ({
ProxyAgent: proxyMocks.ProxyAgent,
fetch: proxyMocks.undiciFetch,
setGlobalDispatcher: proxyMocks.setGlobalDispatcher,
}));
({ getProxyUrlFromFetch, makeProxyFetch } = await import("./proxy.js"));
});
it("uses undici fetch with ProxyAgent dispatcher", async () => {
const proxyUrl = "http://proxy.test:8080";
proxyMocks.undiciFetch.mockResolvedValue({ ok: true });
const proxyFetch = makeProxyFetch(proxyUrl);
await proxyFetch("https://api.telegram.org/bot123/getMe");
expect(proxyMocks.proxyAgentSpy).toHaveBeenCalledWith(proxyUrl);
expect(proxyMocks.undiciFetch).toHaveBeenCalledWith(
"https://api.telegram.org/bot123/getMe",
expect.objectContaining({ dispatcher: proxyMocks.getLastAgent() }),
);
expect(proxyMocks.setGlobalDispatcher).not.toHaveBeenCalled();
});
it("attaches proxy metadata for resolver transport handling", () => {
const proxyUrl = "http://proxy.test:8080";
const proxyFetch = makeProxyFetch(proxyUrl);
expect(getProxyUrlFromFetch(proxyFetch)).toBe(proxyUrl);
});
});

View File

@@ -1,64 +0,0 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
const mocks = vi.hoisted(() => {
const undiciFetch = vi.fn();
const proxyAgentSpy = vi.fn();
const setGlobalDispatcher = vi.fn();
class ProxyAgent {
static lastCreated: ProxyAgent | undefined;
proxyUrl: string;
constructor(proxyUrl: string) {
this.proxyUrl = proxyUrl;
ProxyAgent.lastCreated = this;
proxyAgentSpy(proxyUrl);
}
}
return {
ProxyAgent,
undiciFetch,
proxyAgentSpy,
setGlobalDispatcher,
getLastAgent: () => ProxyAgent.lastCreated,
};
});
let getProxyUrlFromFetch: typeof import("./proxy.js").getProxyUrlFromFetch;
let makeProxyFetch: typeof import("./proxy.js").makeProxyFetch;
describe("makeProxyFetch", () => {
beforeEach(async () => {
vi.resetModules();
mocks.undiciFetch.mockReset();
mocks.proxyAgentSpy.mockClear();
mocks.setGlobalDispatcher.mockClear();
vi.doMock("undici", () => ({
ProxyAgent: mocks.ProxyAgent,
fetch: mocks.undiciFetch,
setGlobalDispatcher: mocks.setGlobalDispatcher,
}));
({ getProxyUrlFromFetch, makeProxyFetch } = await import("./proxy.js"));
});
it("uses undici fetch with ProxyAgent dispatcher", async () => {
const proxyUrl = "http://proxy.test:8080";
mocks.undiciFetch.mockResolvedValue({ ok: true });
const proxyFetch = makeProxyFetch(proxyUrl);
await proxyFetch("https://api.telegram.org/bot123/getMe");
expect(mocks.proxyAgentSpy).toHaveBeenCalledWith(proxyUrl);
expect(mocks.undiciFetch).toHaveBeenCalledWith(
"https://api.telegram.org/bot123/getMe",
expect.objectContaining({ dispatcher: mocks.getLastAgent() }),
);
expect(mocks.setGlobalDispatcher).not.toHaveBeenCalled();
});
it("attaches proxy metadata for resolver transport handling", () => {
const proxyUrl = "http://proxy.test:8080";
const proxyFetch = makeProxyFetch(proxyUrl);
expect(getProxyUrlFromFetch(proxyFetch)).toBe(proxyUrl);
});
});

View File

@@ -1,77 +0,0 @@
import type { ChannelAccountSnapshot } from "openclaw/plugin-sdk/channel-contract";
import { describe, expect, it } from "vitest";
import { collectTelegramStatusIssues } from "./status-issues.js";
describe("collectTelegramStatusIssues", () => {
it("reports privacy-mode and wildcard unmentioned-group configuration risks", () => {
const issues = collectTelegramStatusIssues([
{
accountId: "main",
enabled: true,
configured: true,
allowUnmentionedGroups: true,
audit: {
hasWildcardUnmentionedGroups: true,
unresolvedGroups: 2,
},
} as ChannelAccountSnapshot,
]);
expect(issues).toEqual(
expect.arrayContaining([
expect.objectContaining({
channel: "telegram",
accountId: "main",
kind: "config",
}),
]),
);
expect(issues.some((issue) => issue.message.includes("privacy mode"))).toBe(true);
expect(issues.some((issue) => issue.message.includes('uses "*"'))).toBe(true);
expect(issues.some((issue) => issue.message.includes("unresolvedGroups=2"))).toBe(true);
});
it("reports unreachable groups with match metadata", () => {
const issues = collectTelegramStatusIssues([
{
accountId: "main",
enabled: true,
configured: true,
audit: {
groups: [
{
chatId: "-100123",
ok: false,
status: "left",
error: "403",
matchKey: "alerts",
matchSource: "channels.telegram.groups",
},
],
},
} as ChannelAccountSnapshot,
]);
expect(issues).toHaveLength(1);
expect(issues[0]).toMatchObject({
channel: "telegram",
accountId: "main",
kind: "runtime",
});
expect(issues[0]?.message).toContain("Group -100123 not reachable");
expect(issues[0]?.message).toContain("alerts");
expect(issues[0]?.message).toContain("channels.telegram.groups");
});
it("ignores accounts that are not both enabled and configured", () => {
expect(
collectTelegramStatusIssues([
{
accountId: "main",
enabled: false,
configured: true,
} as ChannelAccountSnapshot,
]),
).toEqual([]);
});
});

View File

@@ -1,5 +1,7 @@
import type { ChannelAccountSnapshot } from "openclaw/plugin-sdk/channel-contract";
import { describe, expect, it } from "vitest";
import { DEFAULT_EMOJIS } from "../../../src/channels/status-reactions.js";
import { collectTelegramStatusIssues } from "./status-issues.js";
import {
buildTelegramStatusReactionVariants,
extractTelegramAllowedEmojiReactions,
@@ -9,6 +11,80 @@ import {
resolveTelegramStatusReactionEmojis,
} from "./status-reaction-variants.js";
describe("collectTelegramStatusIssues", () => {
it("reports privacy-mode and wildcard unmentioned-group configuration risks", () => {
const issues = collectTelegramStatusIssues([
{
accountId: "main",
enabled: true,
configured: true,
allowUnmentionedGroups: true,
audit: {
hasWildcardUnmentionedGroups: true,
unresolvedGroups: 2,
},
} as ChannelAccountSnapshot,
]);
expect(issues).toEqual(
expect.arrayContaining([
expect.objectContaining({
channel: "telegram",
accountId: "main",
kind: "config",
}),
]),
);
expect(issues.some((issue) => issue.message.includes("privacy mode"))).toBe(true);
expect(issues.some((issue) => issue.message.includes('uses "*"'))).toBe(true);
expect(issues.some((issue) => issue.message.includes("unresolvedGroups=2"))).toBe(true);
});
it("reports unreachable groups with match metadata", () => {
const issues = collectTelegramStatusIssues([
{
accountId: "main",
enabled: true,
configured: true,
audit: {
groups: [
{
chatId: "-100123",
ok: false,
status: "left",
error: "403",
matchKey: "alerts",
matchSource: "channels.telegram.groups",
},
],
},
} as ChannelAccountSnapshot,
]);
expect(issues).toHaveLength(1);
expect(issues[0]).toMatchObject({
channel: "telegram",
accountId: "main",
kind: "runtime",
});
expect(issues[0]?.message).toContain("Group -100123 not reachable");
expect(issues[0]?.message).toContain("alerts");
expect(issues[0]?.message).toContain("channels.telegram.groups");
});
it("ignores accounts that are not both enabled and configured", () => {
expect(
collectTelegramStatusIssues([
{
accountId: "main",
enabled: false,
configured: true,
} as ChannelAccountSnapshot,
]),
).toEqual([]);
});
});
describe("resolveTelegramStatusReactionEmojis", () => {
it("falls back to Telegram-safe defaults for empty overrides", () => {
const result = resolveTelegramStatusReactionEmojis({