|
1 | 1 | // Msteams tests cover graph upload plugin behavior. |
2 | 2 | import { createServer, type Server } from "node:http"; |
3 | | -import type { AddressInfo } from "node:net"; |
4 | 3 | import { withFetchPreconnect } from "openclaw/plugin-sdk/test-env"; |
5 | 4 | import { afterEach, describe, expect, it, vi } from "vitest"; |
6 | 5 | import { buildTeamsFileInfoCard } from "./graph-chat.js"; |
@@ -265,7 +264,7 @@ async function listenLoopbackServer(server: Server): Promise<number> { |
265 | 264 | reject(new Error("expected loopback TCP address")); |
266 | 265 | return; |
267 | 266 | } |
268 | | - resolve((address as AddressInfo).port); |
| 267 | + resolve(address.port); |
269 | 268 | }); |
270 | 269 | }); |
271 | 270 | } |
@@ -415,6 +414,52 @@ describe("graph-upload readProviderJsonResponse loopback proof", () => { |
415 | 414 | await closeServer(server); |
416 | 415 | } |
417 | 416 | }); |
| 417 | + |
| 418 | + it("uploadToOneDrive rejects an oversized success JSON body from a real loopback HTTP server", async () => { |
| 419 | + const server = createServer((_req, res) => { |
| 420 | + res.writeHead(200, { "content-type": "application/json" }); |
| 421 | + const chunk = Buffer.alloc(64 * 1024, 0x20); |
| 422 | + let remaining = 257; // >16 MiB when combined with the JSON prefix. |
| 423 | + res.write('{"id":"item-big","webUrl":"https://example.com/big","name":"big.txt","padding":"'); |
| 424 | + const writeNext = () => { |
| 425 | + if (remaining <= 0) { |
| 426 | + res.end('"}'); |
| 427 | + return; |
| 428 | + } |
| 429 | + remaining -= 1; |
| 430 | + if (res.write(chunk)) { |
| 431 | + setImmediate(writeNext); |
| 432 | + } else { |
| 433 | + res.once("drain", writeNext); |
| 434 | + } |
| 435 | + }; |
| 436 | + writeNext(); |
| 437 | + }); |
| 438 | + const port = await listenLoopbackServer(server); |
| 439 | + |
| 440 | + try { |
| 441 | + const realFetch = globalThis.fetch.bind(globalThis); |
| 442 | + vi.stubGlobal( |
| 443 | + "fetch", |
| 444 | + withFetchPreconnect(async (input: RequestInfo | URL, init?: RequestInit) => { |
| 445 | + const url = new URL(input instanceof Request ? input.url : String(input)); |
| 446 | + const loopback = new URL(`${url.pathname}${url.search}`, `http://127.0.0.1:${port}`); |
| 447 | + return realFetch(loopback, init); |
| 448 | + }), |
| 449 | + ); |
| 450 | + |
| 451 | + await expect( |
| 452 | + uploadToOneDrive({ buffer: Buffer.from("x"), filename: "big.txt", tokenProvider }), |
| 453 | + ).rejects.toThrow( |
| 454 | + "msteams.graph-upload.uploadOneDriveFile: JSON response exceeds 16777216 bytes", |
| 455 | + ); |
| 456 | + console.log( |
| 457 | + "[msteams graph-upload loopback proof] oversized JSON rejected by bounded reader", |
| 458 | + ); |
| 459 | + } finally { |
| 460 | + await closeServer(server); |
| 461 | + } |
| 462 | + }); |
418 | 463 | }); |
419 | 464 |
|
420 | 465 | describe("buildTeamsFileInfoCard", () => { |
|
0 commit comments