






















@@ -81,7 +81,7 @@ function installRuntime(): MockRuntime {
8181}
82828383function createMockFetch(entries: Array<{ match: RegExp; response: Response }>): typeof fetch {
84-return (async (input: RequestInfo | URL) => {
84+return vi.fn(async (input: RequestInfo | URL) => {
8585const url =
8686typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
8787const entry = entries.find((e) => e.match.test(url));
@@ -175,6 +175,7 @@ describe("downloadMSTeamsBotFrameworkAttachment", () => {
175175tokenProvider: buildTokenProvider(),
176176maxBytes: 10_000_000,
177177 fetchFn,
178+fetchFnSupportsDispatcher: true,
178179resolveFn: resolvePublicHost,
179180});
180181@@ -198,6 +199,7 @@ describe("downloadMSTeamsBotFrameworkAttachment", () => {
198199tokenProvider: buildTokenProvider(),
199200maxBytes: 10_000_000,
200201 fetchFn,
202+fetchFnSupportsDispatcher: true,
201203resolveFn: resolvePublicHost,
202204});
203205@@ -218,6 +220,7 @@ describe("downloadMSTeamsBotFrameworkAttachment", () => {
218220tokenProvider: buildTokenProvider(),
219221maxBytes: 10_000_000,
220222 fetchFn,
223+fetchFnSupportsDispatcher: true,
221224resolveFn: resolvePublicHost,
222225});
223226@@ -258,6 +261,7 @@ describe("downloadMSTeamsBotFrameworkAttachment", () => {
258261tokenProvider: buildTokenProvider(),
259262maxBytes: 10_000_000,
260263 fetchFn,
264+fetchFnSupportsDispatcher: true,
261265resolveFn: resolvePublicHost,
262266});
263267@@ -325,15 +329,8 @@ describe("downloadMSTeamsBotFrameworkAttachment", () => {
325329expect(fetchFn).not.toHaveBeenCalled();
326330});
327331328-describe("Node 24+ dispatcher bypass (issue #63396)", () => {
329-it("drives the caller's fetchFn directly without the pinned undici dispatcher", async () => {
330-// Regression: before the fix, fetchBotFrameworkAttachment* routed
331-// through `fetchWithSsrFGuard`, which installs a `createPinnedDispatcher`
332-// incompatible with Node 24+'s built-in undici v7. Downloads failed with
333-// "invalid onRequestStart method". The fix switches to
334-// `safeFetchWithPolicy`, which calls the supplied `fetchFn` directly
335-// and never attaches a pinned dispatcher. Verify the caller's `fetchFn`
336-// is invoked (no dispatcher in init).
332+describe("guarded attachment fetches", () => {
333+it("drives dispatcher-aware caller fetchFn hooks through a pinned dispatcher", async () => {
337334const fileBytes = Buffer.from("BFBYTES", "utf-8");
338335const fetchCalls: Array<{ url: string; init?: RequestInit }> = [];
339336const fetchFn: typeof fetch = (async (input: RequestInfo | URL, init?: RequestInit) => {
@@ -365,20 +362,20 @@ describe("downloadMSTeamsBotFrameworkAttachment", () => {
365362tokenProvider: buildTokenProvider(),
366363maxBytes: 10_000_000,
367364 fetchFn,
365+fetchFnSupportsDispatcher: true,
368366resolveFn: resolvePublicHost,
369367});
370368371369expect(media?.path).toBe(runtime.savePath);
372370expect(media?.contentType).toBe(runtime.savedContentType);
373371// Both the attachment info call and the view call should be observed,
374-// confirming the direct fetch path was taken (no dispatcher interception).
372+// confirming the guarded fetch path still preserves caller fetch hooks.
375373expect(fetchCalls).toHaveLength(2);
376374expect(fetchCalls[0].url.endsWith("/v3/attachments/att-1")).toBe(true);
377375expect(fetchCalls[1].url.endsWith("/v3/attachments/att-1/views/original")).toBe(true);
378-// Verify no pinned undici dispatcher is attached on either request.
379376for (const call of fetchCalls) {
380377const init = call.init as RequestInit & { dispatcher?: unknown };
381-expect(init?.dispatcher).toBeUndefined();
378+expect(init?.dispatcher).toBeDefined();
382379}
383380});
384381@@ -396,6 +393,7 @@ describe("downloadMSTeamsBotFrameworkAttachment", () => {
396393tokenProvider: buildTokenProvider(),
397394maxBytes: 10_000_000,
398395 fetchFn,
396+fetchFnSupportsDispatcher: true,
399397resolveFn: resolvePublicHost,
400398 logger,
401399});
@@ -433,6 +431,7 @@ describe("downloadMSTeamsBotFrameworkAttachment", () => {
433431tokenProvider: buildTokenProvider(),
434432maxBytes: 10_000_000,
435433 fetchFn,
434+fetchFnSupportsDispatcher: true,
436435resolveFn: resolvePublicHost,
437436 logger,
438437});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。