From bb3ea2137b6b165698c335339a161eff6f1d61ca Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 3 Apr 2026 11:35:07 +0100 Subject: [PATCH] test: move telegram fetch coverage into extensions --- .../bot/delivery.resolve-media-retry.test.ts | 44 ++- .../telegram/src/fetch.network-policy.test.ts | 347 ------------------ extensions/telegram/src/fetch.test.ts | 56 +++ test/fixtures/test-parallel.behavior.json | 8 +- test/fixtures/test-timings.channels.json | 6 - test/fixtures/test-timings.extensions.json | 10 +- test/scripts/test-parallel.test.ts | 6 +- test/vitest-scoped-config.test.ts | 21 +- vitest.channel-paths.mjs | 3 +- 9 files changed, 132 insertions(+), 369 deletions(-) delete mode 100644 extensions/telegram/src/fetch.network-policy.test.ts diff --git a/extensions/telegram/src/bot/delivery.resolve-media-retry.test.ts b/extensions/telegram/src/bot/delivery.resolve-media-retry.test.ts index 59b6afa0b0b..0b3a615ed36 100644 --- a/extensions/telegram/src/bot/delivery.resolve-media-retry.test.ts +++ b/extensions/telegram/src/bot/delivery.resolve-media-retry.test.ts @@ -320,7 +320,12 @@ describe("resolveMedia getFile retry", () => { it("uses caller-provided fetch impl for file downloads", async () => { const getFile = vi.fn().mockResolvedValue({ file_path: "documents/file_42.pdf" }); const callerFetch = vi.fn() as unknown as typeof fetch; - const callerTransport = { fetch: callerFetch, sourceFetch: callerFetch }; + const dispatcherAttempts = [{ dispatcherPolicy: { mode: "direct" as const } }]; + const callerTransport = { + fetch: callerFetch, + sourceFetch: callerFetch, + dispatcherAttempts, + }; fetchRemoteMedia.mockResolvedValueOnce({ buffer: Buffer.from("pdf-data"), contentType: "application/pdf", @@ -339,6 +344,13 @@ describe("resolveMedia getFile retry", () => { expect(fetchRemoteMedia).toHaveBeenCalledWith( expect.objectContaining({ fetchImpl: callerFetch, + dispatcherAttempts, + shouldRetryFetchError: expect.any(Function), + readIdleTimeoutMs: 30_000, + ssrfPolicy: { + allowRfc2544BenchmarkRange: true, + hostnameAllowlist: ["api.telegram.org"], + }, }), ); }); @@ -369,6 +381,36 @@ describe("resolveMedia getFile retry", () => { ); }); + it("allows an explicit Telegram apiRoot host without broadening the default SSRF allowlist", async () => { + const getFile = vi.fn().mockResolvedValue({ file_path: "documents/file_42.pdf" }); + fetchRemoteMedia.mockResolvedValueOnce({ + buffer: Buffer.from("pdf-data"), + contentType: "application/pdf", + fileName: "file_42.pdf", + }); + saveMediaBuffer.mockResolvedValueOnce({ + path: "/tmp/file_42---uuid.pdf", + contentType: "application/pdf", + }); + + await resolveMediaWithDefaults(makeCtx("document", getFile), { + apiRoot: "https://telegram.internal:8443/custom/", + dangerouslyAllowPrivateNetwork: true, + }); + + expect(fetchRemoteMedia).toHaveBeenCalledWith( + expect.objectContaining({ + url: `https://telegram.internal:8443/custom/file/bot${BOT_TOKEN}/documents/file_42.pdf`, + ssrfPolicy: { + hostnameAllowlist: ["api.telegram.org", "telegram.internal"], + allowedHostnames: ["telegram.internal"], + allowPrivateNetwork: true, + allowRfc2544BenchmarkRange: true, + }, + }), + ); + }); + it("uses local absolute file paths directly for media downloads", async () => { const getFile = vi.fn().mockResolvedValue({ file_path: "/var/lib/telegram-bot-api/file.pdf" }); diff --git a/extensions/telegram/src/fetch.network-policy.test.ts b/extensions/telegram/src/fetch.network-policy.test.ts deleted file mode 100644 index 4e5f4ff3b9f..00000000000 --- a/extensions/telegram/src/fetch.network-policy.test.ts +++ /dev/null @@ -1,347 +0,0 @@ -import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; - -const undiciMocks = vi.hoisted(() => { - const createDispatcherCtor = | string>() => - vi.fn(function MockDispatcher(this: { options?: T }, options?: T) { - this.options = options; - }); - - return { - fetch: vi.fn(), - agentCtor: createDispatcherCtor>(), - envHttpProxyAgentCtor: createDispatcherCtor>(), - proxyAgentCtor: createDispatcherCtor | string>(), - }; -}); - -vi.mock("undici", () => ({ - Agent: undiciMocks.agentCtor, - EnvHttpProxyAgent: undiciMocks.envHttpProxyAgentCtor, - ProxyAgent: undiciMocks.proxyAgentCtor, - fetch: undiciMocks.fetch, -})); - -let fetchRemoteMedia: typeof import("../../../src/media/fetch.js").fetchRemoteMedia; -let resolveTelegramTransport: typeof import("./fetch.js").resolveTelegramTransport; -let shouldRetryTelegramTransportFallback: typeof import("./fetch.js").shouldRetryTelegramTransportFallback; -let makeProxyFetch: typeof import("./proxy.js").makeProxyFetch; -let TEST_UNDICI_RUNTIME_DEPS_KEY: typeof import("../../../src/infra/net/undici-runtime.js").TEST_UNDICI_RUNTIME_DEPS_KEY; - -describe("fetchRemoteMedia telegram network policy", () => { - type LookupFn = NonNullable[0]["lookupFn"]>; - - beforeAll(async () => { - ({ TEST_UNDICI_RUNTIME_DEPS_KEY } = await import("../../../src/infra/net/undici-runtime.js")); - ({ fetchRemoteMedia } = await import("../../../src/media/fetch.js")); - ({ resolveTelegramTransport, shouldRetryTelegramTransportFallback } = - await import("./fetch.js")); - ({ makeProxyFetch } = await import("./proxy.js")); - }); - - beforeEach(() => { - undiciMocks.fetch.mockReset(); - undiciMocks.agentCtor.mockClear(); - undiciMocks.envHttpProxyAgentCtor.mockClear(); - undiciMocks.proxyAgentCtor.mockClear(); - (globalThis as Record)[TEST_UNDICI_RUNTIME_DEPS_KEY] = { - Agent: undiciMocks.agentCtor, - EnvHttpProxyAgent: undiciMocks.envHttpProxyAgentCtor, - ProxyAgent: undiciMocks.proxyAgentCtor, - }; - }); - - function createTelegramFetchFailedError(code: string): Error { - return Object.assign(new TypeError("fetch failed"), { - cause: { code }, - }); - } - - afterEach(() => { - Reflect.deleteProperty(globalThis as object, TEST_UNDICI_RUNTIME_DEPS_KEY); - vi.unstubAllEnvs(); - }); - - afterAll(() => { - Reflect.deleteProperty(globalThis as object, TEST_UNDICI_RUNTIME_DEPS_KEY); - }); - - it("preserves Telegram resolver transport policy for file downloads", async () => { - const lookupFn = vi.fn(async () => [ - { address: "149.154.167.220", family: 4 }, - ]) as unknown as LookupFn; - undiciMocks.fetch.mockResolvedValueOnce( - new Response(new Uint8Array([0xff, 0xd8, 0xff, 0x00]), { - status: 200, - headers: { "content-type": "image/jpeg" }, - }), - ); - - const telegramTransport = resolveTelegramTransport(undefined, { - network: { - autoSelectFamily: true, - dnsResultOrder: "verbatim", - }, - }); - - await fetchRemoteMedia({ - url: "https://api.telegram.org/file/bottok/photos/1.jpg", - fetchImpl: telegramTransport.sourceFetch, - dispatcherAttempts: telegramTransport.dispatcherAttempts, - lookupFn, - maxBytes: 1024, - ssrfPolicy: { - allowedHostnames: ["api.telegram.org"], - allowRfc2544BenchmarkRange: true, - }, - }); - - const init = undiciMocks.fetch.mock.calls[0]?.[1] as - | (RequestInit & { - dispatcher?: { - options?: { - connect?: Record; - }; - }; - }) - | undefined; - - expect(init?.dispatcher?.options?.connect).toEqual( - expect.objectContaining({ - autoSelectFamily: true, - autoSelectFamilyAttemptTimeout: 300, - lookup: expect.any(Function), - }), - ); - }); - - it("keeps explicit proxy routing for file downloads", async () => { - const lookupFn = vi.fn(async () => [ - { address: "149.154.167.220", family: 4 }, - ]) as unknown as LookupFn; - undiciMocks.fetch.mockResolvedValueOnce( - new Response(new Uint8Array([0x25, 0x50, 0x44, 0x46]), { - status: 200, - headers: { "content-type": "application/pdf" }, - }), - ); - - const telegramTransport = resolveTelegramTransport(makeProxyFetch("http://127.0.0.1:7890"), { - network: { - autoSelectFamily: false, - dnsResultOrder: "ipv4first", - }, - }); - - await fetchRemoteMedia({ - url: "https://api.telegram.org/file/bottok/files/1.pdf", - fetchImpl: telegramTransport.sourceFetch, - dispatcherAttempts: telegramTransport.dispatcherAttempts, - lookupFn, - maxBytes: 1024, - ssrfPolicy: { - allowedHostnames: ["api.telegram.org"], - allowRfc2544BenchmarkRange: true, - }, - }); - - const init = undiciMocks.fetch.mock.calls[0]?.[1] as - | (RequestInit & { - dispatcher?: { - options?: { - uri?: string; - requestTls?: Record; - }; - }; - }) - | undefined; - - expect(init?.dispatcher?.options?.uri).toBe("http://127.0.0.1:7890"); - expect(init?.dispatcher?.options?.requestTls).toEqual( - expect.objectContaining({ - autoSelectFamily: false, - lookup: expect.any(Function), - }), - ); - expect(undiciMocks.proxyAgentCtor).toHaveBeenCalled(); - }); - - it("retries Telegram file downloads with IPv4 fallback when the first fetch fails", async () => { - const lookupFn = vi.fn(async () => [ - { address: "149.154.167.220", family: 4 }, - { address: "2001:67c:4e8:f004::9", family: 6 }, - ]) as unknown as LookupFn; - undiciMocks.fetch - .mockRejectedValueOnce(createTelegramFetchFailedError("EHOSTUNREACH")) - .mockResolvedValueOnce( - new Response(new Uint8Array([0xff, 0xd8, 0xff, 0x00]), { - status: 200, - headers: { "content-type": "image/jpeg" }, - }), - ); - - const telegramTransport = resolveTelegramTransport(undefined, { - network: { - autoSelectFamily: true, - dnsResultOrder: "ipv4first", - }, - }); - - await fetchRemoteMedia({ - url: "https://api.telegram.org/file/bottok/photos/2.jpg", - fetchImpl: telegramTransport.sourceFetch, - dispatcherAttempts: telegramTransport.dispatcherAttempts, - shouldRetryFetchError: shouldRetryTelegramTransportFallback, - lookupFn, - maxBytes: 1024, - ssrfPolicy: { - allowedHostnames: ["api.telegram.org"], - allowRfc2544BenchmarkRange: true, - }, - }); - - const firstInit = undiciMocks.fetch.mock.calls[0]?.[1] as - | (RequestInit & { - dispatcher?: { - options?: { - connect?: Record; - }; - }; - }) - | undefined; - const secondInit = undiciMocks.fetch.mock.calls[1]?.[1] as - | (RequestInit & { - dispatcher?: { - options?: { - connect?: Record; - }; - }; - }) - | undefined; - - expect(undiciMocks.fetch).toHaveBeenCalledTimes(2); - expect(firstInit?.dispatcher?.options?.connect).toEqual( - expect.objectContaining({ - autoSelectFamily: true, - autoSelectFamilyAttemptTimeout: 300, - lookup: expect.any(Function), - }), - ); - expect(secondInit?.dispatcher?.options?.connect).toEqual( - expect.objectContaining({ - family: 4, - autoSelectFamily: false, - lookup: expect.any(Function), - }), - ); - }); - - it("retries Telegram file downloads with pinned Telegram IP after IPv4 fallback fails", async () => { - const lookupFn = vi.fn(async () => [ - { address: "149.154.167.221", family: 4 }, - { address: "2001:67c:4e8:f004::9", family: 6 }, - ]) as unknown as LookupFn; - undiciMocks.fetch - .mockRejectedValueOnce(createTelegramFetchFailedError("EHOSTUNREACH")) - .mockRejectedValueOnce(createTelegramFetchFailedError("ETIMEDOUT")) - .mockResolvedValueOnce( - new Response(new Uint8Array([0xff, 0xd8, 0xff, 0x00]), { - status: 200, - headers: { "content-type": "image/jpeg" }, - }), - ); - - const telegramTransport = resolveTelegramTransport(undefined, { - network: { - autoSelectFamily: true, - dnsResultOrder: "ipv4first", - }, - }); - - await fetchRemoteMedia({ - url: "https://api.telegram.org/file/bottok/photos/3.jpg", - fetchImpl: telegramTransport.sourceFetch, - dispatcherAttempts: telegramTransport.dispatcherAttempts, - shouldRetryFetchError: shouldRetryTelegramTransportFallback, - lookupFn, - maxBytes: 1024, - ssrfPolicy: { - allowedHostnames: ["api.telegram.org"], - allowRfc2544BenchmarkRange: true, - }, - }); - - const thirdInit = undiciMocks.fetch.mock.calls[2]?.[1] as - | (RequestInit & { - dispatcher?: { - options?: { - connect?: Record; - }; - }; - }) - | undefined; - const callback = vi.fn(); - ( - thirdInit?.dispatcher?.options?.connect?.lookup as - | (( - hostname: string, - callback: (err: null, address: string, family: number) => void, - ) => void) - | undefined - )?.("api.telegram.org", callback); - - expect(undiciMocks.fetch).toHaveBeenCalledTimes(3); - expect(thirdInit?.dispatcher?.options?.connect).toEqual( - expect.objectContaining({ - family: 4, - autoSelectFamily: false, - lookup: expect.any(Function), - }), - ); - expect(callback).toHaveBeenCalledWith(null, "149.154.167.220", 4); - }); - - it("preserves both primary and final fallback errors when Telegram media retry chain fails", async () => { - const lookupFn = vi.fn(async () => [ - { address: "149.154.167.220", family: 4 }, - { address: "2001:67c:4e8:f004::9", family: 6 }, - ]) as unknown as LookupFn; - const primaryError = createTelegramFetchFailedError("EHOSTUNREACH"); - const ipv4Error = createTelegramFetchFailedError("ETIMEDOUT"); - const fallbackError = createTelegramFetchFailedError("ETIMEDOUT"); - undiciMocks.fetch - .mockRejectedValueOnce(primaryError) - .mockRejectedValueOnce(ipv4Error) - .mockRejectedValueOnce(fallbackError); - - const telegramTransport = resolveTelegramTransport(undefined, { - network: { - autoSelectFamily: true, - dnsResultOrder: "ipv4first", - }, - }); - - await expect( - fetchRemoteMedia({ - url: "https://api.telegram.org/file/bottok/photos/4.jpg", - fetchImpl: telegramTransport.sourceFetch, - dispatcherAttempts: telegramTransport.dispatcherAttempts, - shouldRetryFetchError: shouldRetryTelegramTransportFallback, - lookupFn, - maxBytes: 1024, - ssrfPolicy: { - allowedHostnames: ["api.telegram.org"], - allowRfc2544BenchmarkRange: true, - }, - }), - ).rejects.toMatchObject({ - name: "MediaFetchError", - code: "fetch_failed", - cause: expect.objectContaining({ - name: "Error", - cause: fallbackError, - attemptErrors: [primaryError, ipv4Error, fallbackError], - primaryError, - }), - }); - }); -}); diff --git a/extensions/telegram/src/fetch.test.ts b/extensions/telegram/src/fetch.test.ts index 0fb8d1e70ed..3860d298851 100644 --- a/extensions/telegram/src/fetch.test.ts +++ b/extensions/telegram/src/fetch.test.ts @@ -79,6 +79,10 @@ let resolveFetch: typeof import("../../../src/infra/fetch.js").resolveFetch; let resolveTelegramFetch: typeof import("./fetch.js").resolveTelegramFetch; let resolveTelegramTransport: typeof import("./fetch.js").resolveTelegramTransport; +type TelegramDispatcherPolicy = NonNullable< + ReturnType["dispatcherAttempts"] +>[number]["dispatcherPolicy"]; + beforeAll(async () => { ({ resolveFetch } = await import("../../../src/infra/fetch.js")); ({ resolveTelegramFetch, resolveTelegramTransport } = await import("./fetch.js")); @@ -393,6 +397,58 @@ describe("resolveTelegramFetch", () => { ); }); + it("exports fallback dispatcher attempts for Telegram media downloads", () => { + const transport = resolveTelegramTransport(undefined, { + network: { + autoSelectFamily: true, + dnsResultOrder: "ipv4first", + }, + }); + + expect(transport.sourceFetch).toBeDefined(); + expect(transport.fetch).not.toBe(transport.sourceFetch); + expect(transport.dispatcherAttempts).toHaveLength(3); + + const [defaultAttempt, ipv4Attempt, pinnedAttempt] = transport.dispatcherAttempts as Array<{ + dispatcherPolicy?: TelegramDispatcherPolicy; + }>; + + expect(defaultAttempt.dispatcherPolicy).toEqual( + expect.objectContaining({ + mode: "direct", + connect: expect.objectContaining({ + autoSelectFamily: true, + autoSelectFamilyAttemptTimeout: 300, + lookup: expect.any(Function), + }), + }), + ); + expect(ipv4Attempt.dispatcherPolicy).toEqual( + expect.objectContaining({ + mode: "direct", + connect: expect.objectContaining({ + family: 4, + autoSelectFamily: false, + lookup: expect.any(Function), + }), + }), + ); + expect(pinnedAttempt.dispatcherPolicy).toEqual( + expect.objectContaining({ + mode: "direct", + pinnedHostname: { + hostname: "api.telegram.org", + addresses: ["149.154.167.220"], + }, + connect: expect.objectContaining({ + family: 4, + autoSelectFamily: false, + lookup: expect.any(Function), + }), + }), + ); + }); + it("does not blind-retry when sticky IPv4 fallback is disallowed for explicit proxy paths", async () => { const { makeProxyFetch } = await import("./proxy.js"); const proxyFetch = makeProxyFetch("http://127.0.0.1:7890"); diff --git a/test/fixtures/test-parallel.behavior.json b/test/fixtures/test-parallel.behavior.json index f7e2b204b6c..a40f4319452 100644 --- a/test/fixtures/test-parallel.behavior.json +++ b/test/fixtures/test-parallel.behavior.json @@ -106,10 +106,6 @@ "file": "extensions/telegram/src/bot.test.ts", "reason": "This Telegram bot runtime suite measured ~819.9 MiB RSS growth locally; keep it in its own forked channel lane so the shared channels worker can recycle immediately after the hotspot file." }, - { - "file": "extensions/telegram/src/fetch.test.ts", - "reason": "This Telegram transport suite measured ~759.3 MiB RSS growth locally; keep it in its own forked channel lane so the shared channels worker can recycle immediately after the hotspot file." - }, { "file": "extensions/telegram/src/sendchataction-401-backoff.test.ts", "reason": "This Telegram send-chat-action backoff suite hoists infra-runtime sleep mocks and remains a relatively heavy shared hotspot; keep it isolated so top-level concurrency can overlap it instead of extending the shared channels batch." @@ -210,6 +206,10 @@ "file": "extensions/line/src/send.test.ts", "reason": "This LINE send suite hoists SDK and account/token mocks; keep it isolated so shared extension workers do not reuse cached send modules that bypass those mocks." }, + { + "file": "extensions/telegram/src/fetch.test.ts", + "reason": "This Telegram transport suite is extension-owned and still measures high RSS locally; keep it in its own forked extensions lane so the shared worker can recycle immediately after the hotspot." + }, { "file": "extensions/tavily/src/tavily-extract-tool.test.ts", "reason": "This extract-tool suite hoists the Tavily client mock and imports lazily; keep it isolated so shared extension workers do not reuse cached tool modules and hit real API-key resolution." diff --git a/test/fixtures/test-timings.channels.json b/test/fixtures/test-timings.channels.json index a87c7c37230..34c40cf7cec 100644 --- a/test/fixtures/test-timings.channels.json +++ b/test/fixtures/test-timings.channels.json @@ -60,15 +60,9 @@ "extensions/discord/src/monitor/message-handler.queue.test.ts": { "durationMs": 3900 }, - "extensions/telegram/src/fetch.test.ts": { - "durationMs": 3500 - }, "extensions/whatsapp/src/monitor-inbox.captures-media-path-image-messages.test.ts": { "durationMs": 3200 }, - "extensions/telegram/src/bot/delivery.resolve-media-retry.test.ts": { - "durationMs": 15830 - }, "extensions/telegram/src/webhook.test.ts": { "durationMs": 2900 }, diff --git a/test/fixtures/test-timings.extensions.json b/test/fixtures/test-timings.extensions.json index 53dfd509266..fae1d20161b 100644 --- a/test/fixtures/test-timings.extensions.json +++ b/test/fixtures/test-timings.extensions.json @@ -1047,9 +1047,13 @@ "durationMs": 2.155517578125, "testCount": 5 }, - "extensions/telegram/src/fetch.network-policy.test.ts": { - "durationMs": 3260, - "testCount": 5 + "extensions/telegram/src/bot/delivery.resolve-media-retry.test.ts": { + "durationMs": 10360, + "testCount": 27 + }, + "extensions/telegram/src/fetch.test.ts": { + "durationMs": 750, + "testCount": 23 } } } diff --git a/test/scripts/test-parallel.test.ts b/test/scripts/test-parallel.test.ts index ce4ddd980e7..b2e9752726a 100644 --- a/test/scripts/test-parallel.test.ts +++ b/test/scripts/test-parallel.test.ts @@ -447,14 +447,14 @@ describe("scripts/test-parallel lane planning", () => { expect(output).not.toContain("vitest.unit.config.ts"); }); - it("routes telegram fetch network policy through the extensions config", () => { + it("routes telegram fetch transport coverage through the extensions config", () => { const output = runPlannerPlan([ "--explain", - bundledPluginFile("telegram", "src/fetch.network-policy.test.ts"), + bundledPluginFile("telegram", "src/fetch.test.ts"), ]); expect(output).toContain("surface=extensions"); - expect(output).toContain("reasons=extensions-surface"); + expect(output).toContain("extensions-surface"); expect(output).toContain("vitest.extensions.config.ts"); expect(output).not.toContain("vitest.channels.config.ts"); }); diff --git a/test/vitest-scoped-config.test.ts b/test/vitest-scoped-config.test.ts index 5e475e35902..54c629707e2 100644 --- a/test/vitest-scoped-config.test.ts +++ b/test/vitest-scoped-config.test.ts @@ -48,6 +48,15 @@ describe("createScopedVitestConfig", () => { expect(config.test?.include).toEqual(["**/*.test.ts"]); expect(config.test?.exclude).toEqual(expect.arrayContaining(["channel/**", "dist/**"])); }); + + it("overrides setup files when a scoped config requests them", () => { + const config = createScopedVitestConfig(["src/example.test.ts"], { + env: {}, + setupFiles: ["test/setup.extensions.ts"], + }); + + expect(config.test?.setupFiles).toEqual(["test/setup.extensions.ts"]); + }); }); describe("scoped vitest configs", () => { @@ -97,19 +106,23 @@ describe("scoped vitest configs", () => { expect(defaultExtensionsConfig.test?.include).toEqual(["**/*.test.ts"]); }); - it("keeps telegram fetch network policy in extensions while excluding other telegram channel suites", () => { + it("keeps telegram fetch transport coverage in extensions while excluding other telegram channel suites", () => { const extensionExcludes = defaultExtensionsConfig.test?.exclude ?? []; expect( extensionExcludes.some((pattern) => path.matchesGlob("telegram/src/fetch.test.ts", pattern)), - ).toBe(true); + ).toBe(false); expect( extensionExcludes.some((pattern) => - path.matchesGlob("telegram/src/fetch.network-policy.test.ts", pattern), + path.matchesGlob("telegram/src/bot/delivery.resolve-media-retry.test.ts", pattern), ), ).toBe(false); expect(defaultChannelsConfig.test?.exclude).toContain( - bundledPluginFile("telegram", "src/fetch.network-policy.test.ts"), + bundledPluginFile("telegram", "src/fetch.test.ts"), ); + expect(defaultChannelsConfig.test?.exclude).toContain( + bundledPluginFile("telegram", "src/bot/delivery.resolve-media-retry.test.ts"), + ); + expect(defaultExtensionsConfig.test?.setupFiles).toEqual(["test/setup.extensions.ts"]); }); it("normalizes gateway include patterns relative to the scoped dir", () => { diff --git a/vitest.channel-paths.mjs b/vitest.channel-paths.mjs index a41ffe5e603..bf6b2dd9b10 100644 --- a/vitest.channel-paths.mjs +++ b/vitest.channel-paths.mjs @@ -8,7 +8,8 @@ import { const normalizeRepoPath = (value) => value.split(path.sep).join("/"); export const extensionRoutedChannelTestFiles = [ - bundledPluginFile("telegram", "src/fetch.network-policy.test.ts"), + bundledPluginFile("telegram", "src/bot/delivery.resolve-media-retry.test.ts"), + bundledPluginFile("telegram", "src/fetch.test.ts"), ]; const extensionRoutedChannelTestFileSet = new Set(extensionRoutedChannelTestFiles);