@@ -342,6 +342,65 @@ describe("FeishuStreamingSession", () => {
|
342 | 342 | "Final replace failed: Error: Replace card content failed with HTTP 500", |
343 | 343 | ); |
344 | 344 | }); |
| 345 | + |
| 346 | +it("bounds streaming token cache lifetime when token expiry overflows", async () => { |
| 347 | +vi.useFakeTimers(); |
| 348 | +vi.setSystemTime(new Date("2026-05-29T12:00:00.000Z")); |
| 349 | +const release = vi.fn(async () => {}); |
| 350 | +const authTokens: string[] = []; |
| 351 | +fetchWithSsrFGuardMock.mockImplementation( |
| 352 | +async ({ url }: { url: string; init?: { body?: string } }) => { |
| 353 | +if (url.includes("/auth/")) { |
| 354 | +const token = `token-${authTokens.length + 1}`; |
| 355 | +authTokens.push(token); |
| 356 | +return { |
| 357 | +response: { |
| 358 | +ok: true, |
| 359 | +json: async () => ({ |
| 360 | +code: 0, |
| 361 | +msg: "ok", |
| 362 | +tenant_access_token: token, |
| 363 | +expire: Number.MAX_SAFE_INTEGER, |
| 364 | +}), |
| 365 | +}, |
| 366 | + release, |
| 367 | +}; |
| 368 | +} |
| 369 | +return { |
| 370 | +response: { |
| 371 | +ok: true, |
| 372 | +json: async () => ({ |
| 373 | +code: 0, |
| 374 | +msg: "ok", |
| 375 | +data: { card_id: `card-${authTokens.length}` }, |
| 376 | +}), |
| 377 | +}, |
| 378 | + release, |
| 379 | +}; |
| 380 | +}, |
| 381 | +); |
| 382 | +const client = { |
| 383 | +im: { |
| 384 | +message: { |
| 385 | +create: vi.fn(async () => ({ code: 0, msg: "ok", data: { message_id: "om_1" } })), |
| 386 | +}, |
| 387 | +}, |
| 388 | +} as never; |
| 389 | + |
| 390 | +await new FeishuStreamingSession(client, { |
| 391 | +appId: "app_unsafe_token_expiry", |
| 392 | +appSecret: "secret", |
| 393 | +}).start("chat_id", "open_id"); |
| 394 | +expect(authTokens).toEqual(["token-1"]); |
| 395 | + |
| 396 | +vi.setSystemTime(Date.now() + 7200 * 1000 - 60_000 + 1); |
| 397 | +await new FeishuStreamingSession(client, { |
| 398 | +appId: "app_unsafe_token_expiry", |
| 399 | +appSecret: "secret", |
| 400 | +}).start("chat_id", "open_id"); |
| 401 | + |
| 402 | +expect(authTokens).toEqual(["token-1", "token-2"]); |
| 403 | +}); |
345 | 404 | }); |
346 | 405 | |
347 | 406 | describe("mergeStreamingText", () => { |
|