Skip to content

Commit 11cef97

Browse files
Dan JonesDan Jones
authored andcommitted
Update tests
1 parent a7f980c commit 11cef97

File tree

1 file changed

+189
-1
lines changed

1 file changed

+189
-1
lines changed

src/query/agent.test.ts

Lines changed: 189 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
import { WeaviateClient } from "weaviate-client";
22
import { QueryAgent } from "./agent.js";
33
import { ApiQueryAgentResponse } from "./response/api-response.js";
4-
import { QueryAgentResponse } from "./response/response.js";
4+
import {
5+
QueryAgentResponse,
6+
ComparisonOperator,
7+
SearchModeResponse,
8+
} from "./response/response.js";
9+
import { QueryAgentSearcher } from "./search.js";
10+
import { ApiSearchModeResponse } from "./response/api-response.js";
11+
import { QueryAgentError } from "./response/error.js";
512

613
it("runs the query agent", async () => {
714
const mockClient = {
@@ -93,3 +100,184 @@ it("runs the query agent", async () => {
93100
display: expect.any(Function),
94101
});
95102
});
103+
104+
it("prepareSearch returns a QueryAgentSearcher", async () => {
105+
const mockClient = {
106+
getConnectionDetails: jest.fn().mockResolvedValue({
107+
host: "test-cluster",
108+
bearerToken: "test-token",
109+
headers: { "X-Provider": "test-key" },
110+
}),
111+
} as unknown as WeaviateClient;
112+
113+
const agent = new QueryAgent(mockClient, {
114+
systemPrompt: "test system prompt",
115+
});
116+
117+
const searcher = agent.prepareSearch("test query");
118+
expect(searcher).toBeInstanceOf(QueryAgentSearcher);
119+
});
120+
121+
it("search-only mode success: caches searches and sends on subsequent request", async () => {
122+
const mockClient = {
123+
getConnectionDetails: jest.fn().mockResolvedValue({
124+
host: "test-cluster",
125+
bearerToken: "test-token",
126+
headers: { "X-Provider": "test-key" },
127+
}),
128+
} as unknown as WeaviateClient;
129+
130+
const capturedBodies: ApiSearchModeResponse<undefined>[] = [];
131+
132+
const apiSuccess: ApiSearchModeResponse<undefined> = {
133+
original_query: "Test this search only mode!",
134+
searches: [
135+
{
136+
queries: ["search query"],
137+
filters: [
138+
[
139+
{
140+
filter_type: "integer",
141+
property_name: "test_property",
142+
operator: ComparisonOperator.GreaterThan,
143+
value: 0,
144+
},
145+
],
146+
],
147+
filter_operators: "AND",
148+
collection: "test_collection",
149+
},
150+
],
151+
usage: {
152+
requests: 0,
153+
request_tokens: undefined,
154+
response_tokens: undefined,
155+
total_tokens: undefined,
156+
details: undefined,
157+
},
158+
total_time: 1.5,
159+
search_results: {
160+
objects: [
161+
{
162+
uuid: "e6dc0a31-76f8-4bd3-b563-677ced6eb557",
163+
metadata: {},
164+
references: {},
165+
vectors: {},
166+
properties: {
167+
test_property: 1.0,
168+
text: "hello",
169+
},
170+
},
171+
{
172+
uuid: "cf5401cc-f4f1-4eb9-a6a1-173d34f94339",
173+
metadata: {},
174+
references: {},
175+
vectors: {},
176+
properties: {
177+
test_property: 2.0,
178+
text: "world!",
179+
},
180+
},
181+
],
182+
},
183+
};
184+
185+
// Mock the API response, and capture the request body to assert later
186+
global.fetch = jest.fn((url, init?: RequestInit) => {
187+
if (init && init.body) {
188+
capturedBodies.push(
189+
JSON.parse(init.body as string) as ApiSearchModeResponse<undefined>,
190+
);
191+
}
192+
return Promise.resolve({
193+
ok: true,
194+
json: () => Promise.resolve(apiSuccess),
195+
} as Response);
196+
}) as jest.Mock;
197+
198+
const agent = new QueryAgent(mockClient);
199+
const searcher = agent.prepareSearch("test query", {
200+
collections: ["test_collection"],
201+
});
202+
203+
const first = await searcher.execute({ limit: 2, offset: 0 });
204+
205+
expect(first).toEqual<SearchModeResponse<undefined>>({
206+
originalQuery: apiSuccess.original_query,
207+
searches: [
208+
{
209+
collection: "test_collection",
210+
queries: ["search query"],
211+
filters: [
212+
[
213+
{
214+
filterType: "integer",
215+
propertyName: "test_property",
216+
operator: ComparisonOperator.GreaterThan,
217+
value: 0,
218+
},
219+
],
220+
],
221+
filterOperators: "AND",
222+
},
223+
],
224+
usage: {
225+
requests: 0,
226+
requestTokens: undefined,
227+
responseTokens: undefined,
228+
totalTokens: undefined,
229+
details: undefined,
230+
},
231+
totalTime: 1.5,
232+
searchResults: apiSuccess.search_results,
233+
});
234+
235+
// First request should have searches: null (generation request)
236+
expect(capturedBodies[0].searches).toBeNull();
237+
const second = await searcher.execute({ limit: 2, offset: 1 });
238+
// Second request should include the original searches (execution request)
239+
expect(capturedBodies[1].searches).toEqual(apiSuccess.searches);
240+
// Response mapping should be the same (because response is mocked)
241+
expect(second).toEqual(first);
242+
});
243+
244+
it("search-only mode failure propagates QueryAgentError", async () => {
245+
const mockClient = {
246+
getConnectionDetails: jest.fn().mockResolvedValue({
247+
host: "test-cluster",
248+
bearerToken: "test-token",
249+
headers: { "X-Provider": "test-key" },
250+
}),
251+
} as unknown as WeaviateClient;
252+
253+
const errorJson = {
254+
error: {
255+
message: "Test error message",
256+
code: "test_error_code",
257+
details: { info: "test detail" },
258+
},
259+
};
260+
261+
global.fetch = jest.fn(() =>
262+
Promise.resolve({
263+
ok: false,
264+
text: () => Promise.resolve(JSON.stringify(errorJson)),
265+
} as Response),
266+
) as jest.Mock;
267+
268+
const agent = new QueryAgent(mockClient);
269+
const searcher = agent.prepareSearch("test query", {
270+
collections: ["test_collection"],
271+
});
272+
273+
try {
274+
await searcher.execute({ limit: 2, offset: 0 });
275+
} catch (err) {
276+
expect(err).toBeInstanceOf(QueryAgentError);
277+
expect(err).toMatchObject({
278+
message: "Test error message",
279+
code: "test_error_code",
280+
details: { info: "test detail" },
281+
});
282+
}
283+
});

0 commit comments

Comments
 (0)