diff --git a/packages/gateway-client/src/event-loop-ready.test.ts b/packages/gateway-client/src/event-loop-ready.test.ts index 1d9f10a38c31..47de0a249a00 100644 --- a/packages/gateway-client/src/event-loop-ready.test.ts +++ b/packages/gateway-client/src/event-loop-ready.test.ts @@ -49,4 +49,66 @@ describe("waitForEventLoopReady", () => { checks: 1, }); }); + + it("resolves ready after consecutive low-drift timer checks", async () => { + vi.useFakeTimers(); + + const readiness = waitForEventLoopReady({ + maxWaitMs: 100, + intervalMs: 10, + consecutiveReadyChecks: 2, + }); + + await vi.advanceTimersByTimeAsync(20); + + await expect(readiness).resolves.toEqual({ + ready: true, + aborted: false, + elapsedMs: 20, + checks: 2, + maxDriftMs: 0, + }); + }); + + it("resolves not-ready when the readiness deadline expires", async () => { + vi.useFakeTimers(); + + const readiness = waitForEventLoopReady({ + maxWaitMs: 5, + intervalMs: 5, + consecutiveReadyChecks: 2, + }); + + await vi.advanceTimersByTimeAsync(5); + + await expect(readiness).resolves.toEqual({ + ready: false, + aborted: false, + elapsedMs: 5, + checks: 1, + maxDriftMs: 0, + }); + }); + + it("clears pending readiness timers when aborted", async () => { + vi.useFakeTimers(); + const controller = new AbortController(); + + const readiness = waitForEventLoopReady({ + maxWaitMs: 100, + intervalMs: 10, + signal: controller.signal, + }); + + controller.abort(); + + await expect(readiness).resolves.toEqual({ + ready: false, + aborted: true, + elapsedMs: 0, + maxDriftMs: 0, + checks: 0, + }); + expect(vi.getTimerCount()).toBe(0); + }); }); diff --git a/src/gateway/event-loop-ready.test.ts b/src/gateway/event-loop-ready.test.ts deleted file mode 100644 index b1be489cfd43..000000000000 --- a/src/gateway/event-loop-ready.test.ts +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Gateway event-loop readiness tests. - */ -import { afterEach, describe, expect, it, vi } from "vitest"; -import { waitForEventLoopReady } from "./event-loop-ready.js"; - -describe("waitForEventLoopReady", () => { - afterEach(() => { - vi.useRealTimers(); - vi.restoreAllMocks(); - }); - - it("falls back when maxWaitMs is non-finite instead of shortening the deadline", async () => { - vi.useFakeTimers(); - const setTimeoutSpy = vi.spyOn(globalThis, "setTimeout"); - - const promise = waitForEventLoopReady({ - maxWaitMs: Number.NaN, - intervalMs: 25, - consecutiveReadyChecks: 2, - }); - - expect(setTimeoutSpy).toHaveBeenLastCalledWith(expect.any(Function), 25); - - await vi.advanceTimersByTimeAsync(50); - - await expect(promise).resolves.toMatchObject({ - ready: true, - checks: 2, - }); - }); - - it("resolves ready after consecutive low-drift timer checks", async () => { - vi.useFakeTimers(); - - const promise = waitForEventLoopReady({ - maxWaitMs: 100, - intervalMs: 10, - consecutiveReadyChecks: 2, - }); - - await vi.advanceTimersByTimeAsync(20); - - await expect(promise).resolves.toEqual({ - ready: true, - aborted: false, - elapsedMs: 20, - checks: 2, - maxDriftMs: 0, - }); - }); - - it("resolves not-ready when the readiness deadline expires", async () => { - vi.useFakeTimers(); - - const promise = waitForEventLoopReady({ - maxWaitMs: 5, - intervalMs: 5, - consecutiveReadyChecks: 2, - }); - - await vi.advanceTimersByTimeAsync(5); - - await expect(promise).resolves.toEqual({ - ready: false, - aborted: false, - elapsedMs: 5, - checks: 1, - maxDriftMs: 0, - }); - }); - - it("clears pending readiness timers when aborted", async () => { - vi.useFakeTimers(); - const controller = new AbortController(); - - const promise = waitForEventLoopReady({ - maxWaitMs: 100, - intervalMs: 10, - signal: controller.signal, - }); - - controller.abort(); - - await expect(promise).resolves.toEqual({ - ready: false, - aborted: true, - elapsedMs: 0, - maxDriftMs: 0, - checks: 0, - }); - expect(vi.getTimerCount()).toBe(0); - }); -}); diff --git a/src/infra/outbound/tool-payload.test.ts b/src/infra/outbound/tool-payload.test.ts deleted file mode 100644 index d65425c2a0f8..000000000000 --- a/src/infra/outbound/tool-payload.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Verifies outbound tool-payload extraction remains the plugin-sdk facade. -import { describe, expect, it } from "vitest"; -import { extractToolPayload as extractSharedToolPayload } from "../../plugin-sdk/tool-payload.js"; -import { extractToolPayload } from "./tool-payload.js"; - -describe("extractToolPayload", () => { - it("re-exports the shared plugin-sdk helper", () => { - expect(extractToolPayload).toBe(extractSharedToolPayload); - }); -}); diff --git a/src/llm/utils/oauth/pkce.test.ts b/src/llm/utils/oauth/pkce.test.ts deleted file mode 100644 index 75aebada45c3..000000000000 --- a/src/llm/utils/oauth/pkce.test.ts +++ /dev/null @@ -1,16 +0,0 @@ -// PKCE tests cover verifier and challenge generation for OAuth flows. -import { describe, expect, it } from "vitest"; -import { generateOAuthState, generatePKCE } from "./pkce.js"; - -describe("OAuth PKCE utilities", () => { - it("generates OAuth state independently from the PKCE verifier", async () => { - const { verifier } = await generatePKCE(); - const state = generateOAuthState(); - const nextState = generateOAuthState(); - - expect(state).toHaveLength(43); - expect(state).not.toBe(verifier); - expect(nextState).toHaveLength(43); - expect(nextState).not.toBe(state); - }); -}); diff --git a/src/plugin-sdk/provider-oauth-runtime.test.ts b/src/plugin-sdk/provider-oauth-runtime.test.ts index af087ff710e1..42ec6e7a0659 100644 --- a/src/plugin-sdk/provider-oauth-runtime.test.ts +++ b/src/plugin-sdk/provider-oauth-runtime.test.ts @@ -1,12 +1,25 @@ // Provider OAuth runtime tests cover PKCE redirects, callback parsing, and token exchange helpers. import { describe, expect, it } from "vitest"; import { + generateOAuthState, + generatePKCE, parseOAuthAuthorizationInput, resolveOAuthTokenExpiresAt, resolveOAuthTokenLifetimeMs, } from "./provider-oauth-runtime.js"; describe("provider OAuth runtime", () => { + it("generates OAuth state independently from the PKCE verifier", async () => { + const { verifier } = await generatePKCE(); + const state = generateOAuthState(); + const nextState = generateOAuthState(); + + expect(state).toHaveLength(43); + expect(state).not.toBe(verifier); + expect(nextState).toHaveLength(43); + expect(nextState).not.toBe(state); + }); + it("parses authorization code input from redirect URLs, query strings, and raw codes", () => { expect( parseOAuthAuthorizationInput("http://localhost/callback?code=oauth-code&state=oauth-state"),