Skip to content

Commit e00a514

Browse files
committed
Add more tests
1 parent d64c62b commit e00a514

File tree

2 files changed

+179
-1
lines changed

2 files changed

+179
-1
lines changed
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
// npx jest src/api/transform/caching/__tests__/vertex.test.ts
2+
3+
import { Anthropic } from "@anthropic-ai/sdk"
4+
5+
import { addCacheBreakpoints } from "../vertex"
6+
7+
describe("addCacheBreakpoints (Vertex)", () => {
8+
it("should return an empty array if input is empty", () => {
9+
const messages: Anthropic.Messages.MessageParam[] = []
10+
const result = addCacheBreakpoints(messages)
11+
expect(result).toEqual([])
12+
expect(result).not.toBe(messages) // Ensure new array.
13+
})
14+
15+
it("should not add breakpoints if there are no user messages", () => {
16+
const messages: Anthropic.Messages.MessageParam[] = [{ role: "assistant", content: "Hello" }]
17+
const originalMessages = JSON.parse(JSON.stringify(messages))
18+
const result = addCacheBreakpoints(messages)
19+
expect(result).toEqual(originalMessages) // Should be unchanged.
20+
expect(result).not.toBe(messages) // Ensure new array.
21+
})
22+
23+
it("should add a breakpoint to the only user message if only one exists", () => {
24+
const messages: Anthropic.Messages.MessageParam[] = [{ role: "user", content: "User message 1" }]
25+
const result = addCacheBreakpoints(messages)
26+
27+
expect(result).toHaveLength(1)
28+
29+
expect(result[0].content).toEqual([
30+
{ type: "text", text: "User message 1", cache_control: { type: "ephemeral" } },
31+
])
32+
33+
expect(result).not.toBe(messages) // Ensure new array.
34+
})
35+
36+
it("should add breakpoints to both user messages if only two exist", () => {
37+
const messages: Anthropic.Messages.MessageParam[] = [
38+
{ role: "user", content: "User message 1" },
39+
{ role: "user", content: "User message 2" },
40+
]
41+
42+
const result = addCacheBreakpoints(messages)
43+
expect(result).toHaveLength(2)
44+
45+
expect(result[0].content).toEqual([
46+
{ type: "text", text: "User message 1", cache_control: { type: "ephemeral" } },
47+
])
48+
49+
expect(result[1].content).toEqual([
50+
{ type: "text", text: "User message 2", cache_control: { type: "ephemeral" } },
51+
])
52+
53+
expect(result).not.toBe(messages) // Ensure new array.
54+
})
55+
56+
it("should add breakpoints only to the last two user messages when more than two exist", () => {
57+
const messages: Anthropic.Messages.MessageParam[] = [
58+
{ role: "user", content: "User message 1" }, // Should not get breakpoint.
59+
{ role: "user", content: "User message 2" }, // Should get breakpoint.
60+
{ role: "user", content: "User message 3" }, // Should get breakpoint.
61+
]
62+
63+
const originalMessage1 = JSON.parse(JSON.stringify(messages[0]))
64+
const result = addCacheBreakpoints(messages)
65+
66+
expect(result).toHaveLength(3)
67+
expect(result[0]).toEqual(originalMessage1)
68+
69+
expect(result[1].content).toEqual([
70+
{ type: "text", text: "User message 2", cache_control: { type: "ephemeral" } },
71+
])
72+
73+
expect(result[2].content).toEqual([
74+
{ type: "text", text: "User message 3", cache_control: { type: "ephemeral" } },
75+
])
76+
77+
expect(result).not.toBe(messages) // Ensure new array.
78+
})
79+
80+
it("should handle assistant messages correctly when finding last two user messages", () => {
81+
const messages: Anthropic.Messages.MessageParam[] = [
82+
{ role: "user", content: "User message 1" }, // Should not get breakpoint.
83+
{ role: "assistant", content: "Assistant response 1" }, // Should be unchanged.
84+
{ role: "user", content: "User message 2" }, // Should get breakpoint (second to last user).
85+
{ role: "assistant", content: "Assistant response 2" }, // Should be unchanged.
86+
{ role: "user", content: "User message 3" }, // Should get breakpoint (last user).
87+
{ role: "assistant", content: "Assistant response 3" }, // Should be unchanged.
88+
]
89+
const originalMessage1 = JSON.parse(JSON.stringify(messages[0]))
90+
const originalAssistant1 = JSON.parse(JSON.stringify(messages[1]))
91+
const originalAssistant2 = JSON.parse(JSON.stringify(messages[3]))
92+
const originalAssistant3 = JSON.parse(JSON.stringify(messages[5]))
93+
94+
const result = addCacheBreakpoints(messages)
95+
expect(result).toHaveLength(6)
96+
97+
expect(result[0]).toEqual(originalMessage1)
98+
expect(result[1]).toEqual(originalAssistant1)
99+
100+
expect(result[2].content).toEqual([
101+
{ type: "text", text: "User message 2", cache_control: { type: "ephemeral" } },
102+
])
103+
104+
expect(result[3]).toEqual(originalAssistant2)
105+
106+
expect(result[4].content).toEqual([
107+
{ type: "text", text: "User message 3", cache_control: { type: "ephemeral" } },
108+
])
109+
110+
expect(result[5]).toEqual(originalAssistant3)
111+
expect(result).not.toBe(messages) // Ensure new array.
112+
})
113+
114+
it("should add breakpoint only to the last text part if content is an array", () => {
115+
const messages: Anthropic.Messages.MessageParam[] = [
116+
{ role: "user", content: "User message 1" }, // Gets breakpoint.
117+
{
118+
role: "user", // Gets breakpoint.
119+
content: [
120+
{ type: "text", text: "First text part." }, // No breakpoint.
121+
{ type: "image", source: { type: "base64", media_type: "image/png", data: "..." } },
122+
{ type: "text", text: "Last text part." }, // Gets breakpoint.
123+
],
124+
},
125+
]
126+
127+
const result = addCacheBreakpoints(messages)
128+
expect(result).toHaveLength(2)
129+
130+
expect(result[0].content).toEqual([
131+
{ type: "text", text: "User message 1", cache_control: { type: "ephemeral" } },
132+
])
133+
134+
expect(result[1].content).toEqual([
135+
{ type: "text", text: "First text part." }, // Unchanged.
136+
{ type: "image", source: { type: "base64", media_type: "image/png", data: "..." } }, // Unchanged.
137+
{ type: "text", text: "Last text part.", cache_control: { type: "ephemeral" } }, // Breakpoint added.
138+
])
139+
140+
expect(result).not.toBe(messages) // Ensure new array.
141+
})
142+
143+
it("should handle array content with no text parts gracefully", () => {
144+
const messages: Anthropic.Messages.MessageParam[] = [
145+
{ role: "user", content: "User message 1" }, // Gets breakpoint.
146+
{
147+
role: "user", // Gets breakpoint, but has no text part to add it to.
148+
content: [{ type: "image", source: { type: "base64", media_type: "image/png", data: "..." } }],
149+
},
150+
]
151+
152+
const originalMessage2 = JSON.parse(JSON.stringify(messages[1]))
153+
154+
const result = addCacheBreakpoints(messages)
155+
expect(result).toHaveLength(2)
156+
157+
expect(result[0].content).toEqual([
158+
{ type: "text", text: "User message 1", cache_control: { type: "ephemeral" } },
159+
])
160+
161+
// Check second user message - should be unchanged as no text part found.
162+
expect(result[1]).toEqual(originalMessage2)
163+
expect(result).not.toBe(messages) // Ensure new array.
164+
})
165+
166+
it("should not modify the original messages array", () => {
167+
const messages: Anthropic.Messages.MessageParam[] = [
168+
{ role: "user", content: "User message 1" },
169+
{ role: "user", content: "User message 2" },
170+
]
171+
const originalMessagesCopy = JSON.parse(JSON.stringify(messages))
172+
173+
addCacheBreakpoints(messages)
174+
175+
// Verify original array is untouched.
176+
expect(messages).toEqual(originalMessagesCopy)
177+
})
178+
})

src/api/transform/caching/vertex.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export function addCacheBreakpoints(messages: Anthropic.Messages.MessageParam[])
1717
)
1818
}
1919

20-
function cachedMessage(message: Anthropic.Messages.MessageParam) {
20+
function cachedMessage(message: Anthropic.Messages.MessageParam): Anthropic.Messages.MessageParam {
2121
// For string content, we convert to array format with optional cache control.
2222
if (typeof message.content === "string") {
2323
return {

0 commit comments

Comments
 (0)