Skip to content

Commit 1d8a20d

Browse files
committed
test(gemini): align errorDetails fixtures with Task.ts consumer contract
What: Change the 429/403 rejection fixtures from object-shaped errorDetails to arrays of google.rpc detail objects (RetryInfo with retryDelay "30s"; ErrorInfo with reason PERMISSION_DENIED), matching what Task.ts backoffAndAnnounce actually consumes via errorDetails.find(). Why: The object fixture pinned a shape the real consumer never sees, so the pass-through tests could not guard the retry-delay parsing path. Impact: Test-only; pins the array contract both rejection paths preserve.
1 parent 85fdd82 commit 1d8a20d

1 file changed

Lines changed: 12 additions & 4 deletions

File tree

‎src/api/providers/__tests__/gemini.spec.ts‎

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -481,9 +481,11 @@ describe("GeminiHandler", () => {
481481
})
482482

483483
it("preserves status and errorDetails when the stream call rejects with a 429", async () => {
484+
// Task.ts backoffAndAnnounce consumes errorDetails as an ARRAY of google.rpc
485+
// detail objects and parses RetryInfo.retryDelay ("<n>s") on 429s.
484486
const rateLimitError = Object.assign(new Error("rate limit exceeded"), {
485487
status: 429,
486-
errorDetails: { retryAfter: 30 },
488+
errorDetails: [{ "@type": "type.googleapis.com/google.rpc.RetryInfo", retryDelay: "30s" }],
487489
})
488490
mockGenerateContentStream.mockRejectedValue(rateLimitError)
489491

@@ -493,7 +495,9 @@ describe("GeminiHandler", () => {
493495

494496
expect(error).toBeInstanceOf(Error)
495497
expect(error.status).toBe(429)
496-
expect(error.errorDetails).toEqual({ retryAfter: 30 })
498+
expect(error.errorDetails).toEqual([
499+
{ "@type": "type.googleapis.com/google.rpc.RetryInfo", retryDelay: "30s" },
500+
])
497501
})
498502
})
499503

@@ -528,9 +532,11 @@ describe("GeminiHandler", () => {
528532
})
529533

530534
it("preserves status and errorDetails when the completion call rejects with a 403", async () => {
535+
// Same consumer contract as the 429 case: errorDetails is an array of
536+
// google.rpc detail objects (ErrorInfo carries the denial reason).
531537
const forbiddenError = Object.assign(new Error("permission denied"), {
532538
status: 403,
533-
errorDetails: { reason: "PERMISSION_DENIED" },
539+
errorDetails: [{ "@type": "type.googleapis.com/google.rpc.ErrorInfo", reason: "PERMISSION_DENIED" }],
534540
})
535541
mockGenerateContent.mockRejectedValue(forbiddenError)
536542

@@ -541,7 +547,9 @@ describe("GeminiHandler", () => {
541547

542548
expect(error).toBeInstanceOf(Error)
543549
expect(error.status).toBe(403)
544-
expect(error.errorDetails).toEqual({ reason: "PERMISSION_DENIED" })
550+
expect(error.errorDetails).toEqual([
551+
{ "@type": "type.googleapis.com/google.rpc.ErrorInfo", reason: "PERMISSION_DENIED" },
552+
])
545553
})
546554

547555
it("should handle empty response", async () => {

0 commit comments

Comments
 (0)