Skip to content

Commit 401867f

Browse files
OrKoNDevtools-frontend LUCI CQ
authored andcommitted
[AI Assistance] Add unit test helpers
Bug: none Change-Id: I1a81e80413d19795b4582a5780c09201d836f802 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6236124 Commit-Queue: Alex Rudenko <[email protected]> Reviewed-by: Nikolay Vitkov <[email protected]>
1 parent 327f6e8 commit 401867f

File tree

7 files changed

+271
-525
lines changed

7 files changed

+271
-525
lines changed

front_end/panels/ai_assistance/agents/AiAgent.test.ts

Lines changed: 41 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,14 @@
33
// found in the LICENSE file.
44

55
import * as Host from '../../../core/host/host.js';
6+
import {mockAidaClient} from '../../../testing/AiAssistanceHelpers.js';
67
import {
78
describeWithEnvironment,
89
} from '../../../testing/EnvironmentHelpers.js';
910
import * as AiAssistance from '../ai_assistance.js';
1011

1112
const {AiAgent, ResponseType, ConversationContext, ErrorType} = AiAssistance;
1213

13-
function mockAidaClient(
14-
fetch: (_: Host.AidaClient.AidaRequest, options?: {signal: AbortSignal}) =>
15-
AsyncGenerator<Host.AidaClient.AidaResponse, void, void>,
16-
): Host.AidaClient.AidaClient {
17-
return {
18-
fetch,
19-
registerClientEvent: () => Promise.resolve({}),
20-
};
21-
}
22-
2314
function mockConversationContext(): AiAssistance.ConversationContext<unknown> {
2415
return new (class extends ConversationContext<unknown>{
2516
override getOrigin(): string {
@@ -70,7 +61,7 @@ describeWithEnvironment('AiAgent', () => {
7061

7162
it('builds a request with a temperature', async () => {
7263
const agent = new AiAgentMock({
73-
aidaClient: {} as Host.AidaClient.AidaClient,
64+
aidaClient: mockAidaClient(),
7465
});
7566
assert.strictEqual(
7667
agent.buildRequest({text: 'test input'}, Host.AidaClient.Role.USER).options?.temperature,
@@ -80,15 +71,15 @@ describeWithEnvironment('AiAgent', () => {
8071

8172
it('builds a request with a temperature -1', async () => {
8273
const agent = new AiAgentMock({
83-
aidaClient: {} as Host.AidaClient.AidaClient,
74+
aidaClient: mockAidaClient(),
8475
});
8576
agent.options.temperature = -1;
8677
assert.isUndefined(agent.buildRequest({text: 'test input'}, Host.AidaClient.Role.USER).options?.temperature);
8778
});
8879

8980
it('builds a request with a model id', async () => {
9081
const agent = new AiAgentMock({
91-
aidaClient: {} as Host.AidaClient.AidaClient,
82+
aidaClient: mockAidaClient(),
9283
});
9384
assert.strictEqual(
9485
agent.buildRequest({text: 'test input'}, Host.AidaClient.Role.USER).options?.model_id,
@@ -98,7 +89,7 @@ describeWithEnvironment('AiAgent', () => {
9889

9990
it('builds a request with logging', async () => {
10091
const agent = new AiAgentMock({
101-
aidaClient: {} as Host.AidaClient.AidaClient,
92+
aidaClient: mockAidaClient(),
10293
serverSideLoggingEnabled: true,
10394
});
10495
assert.isFalse(
@@ -107,7 +98,7 @@ describeWithEnvironment('AiAgent', () => {
10798

10899
it('builds a request without logging', async () => {
109100
const agent = new AiAgentMock({
110-
aidaClient: {} as Host.AidaClient.AidaClient,
101+
aidaClient: mockAidaClient(),
111102
serverSideLoggingEnabled: false,
112103
});
113104
assert.isTrue(agent
@@ -121,7 +112,7 @@ describeWithEnvironment('AiAgent', () => {
121112

122113
it('builds a request with input', async () => {
123114
const agent = new AiAgentMock({
124-
aidaClient: {} as Host.AidaClient.AidaClient,
115+
aidaClient: mockAidaClient(),
125116
serverSideLoggingEnabled: false,
126117
});
127118
const request = agent.buildRequest({text: 'test input'}, Host.AidaClient.Role.USER);
@@ -131,15 +122,15 @@ describeWithEnvironment('AiAgent', () => {
131122

132123
it('builds a request with a sessionId', async () => {
133124
const agent = new AiAgentMock({
134-
aidaClient: {} as Host.AidaClient.AidaClient,
125+
aidaClient: mockAidaClient(),
135126
});
136127
const request = agent.buildRequest({text: 'test input'}, Host.AidaClient.Role.USER);
137128
assert.strictEqual(request.metadata?.string_session_id, 'sessionId');
138129
});
139130

140131
it('builds a request with preamble', async () => {
141132
const agent = new AiAgentMock({
142-
aidaClient: {} as Host.AidaClient.AidaClient,
133+
aidaClient: mockAidaClient(),
143134
});
144135
const request = agent.buildRequest({text: 'test input'}, Host.AidaClient.Role.USER);
145136
assert.deepEqual(request.current_message?.parts[0], {text: 'test input'});
@@ -164,7 +155,7 @@ describeWithEnvironment('AiAgent', () => {
164155
}
165156

166157
const agent = new AiAgentMockWithoutPreamble({
167-
aidaClient: {} as Host.AidaClient.AidaClient,
158+
aidaClient: mockAidaClient(),
168159
});
169160
const request = agent.buildRequest({text: 'test input'}, Host.AidaClient.Role.USER);
170161
assert.deepEqual(request.current_message?.parts[0], {text: 'test input'});
@@ -173,21 +164,10 @@ describeWithEnvironment('AiAgent', () => {
173164
});
174165

175166
it('builds a request with chat history', async () => {
176-
let count = 0;
177-
async function* generateAndAnswer() {
178-
if (count === 0) {
179-
yield {
180-
explanation: 'answer',
181-
metadata: {},
182-
completed: true,
183-
};
184-
}
185-
186-
count++;
187-
}
188-
189167
const agent = new AiAgentMock({
190-
aidaClient: mockAidaClient(generateAndAnswer),
168+
aidaClient: mockAidaClient([[{
169+
explanation: 'answer',
170+
}]]),
191171
serverSideLoggingEnabled: true,
192172
});
193173
await Array.fromAsync(agent.run('question', {selected: null}));
@@ -207,26 +187,10 @@ describeWithEnvironment('AiAgent', () => {
207187
});
208188

209189
it('builds a request with aborted query in history', async () => {
210-
let count = 0;
211-
async function* generateAndAnswer(_: Host.AidaClient.AidaRequest, options?: {signal?: AbortSignal}) {
212-
if (options?.signal?.aborted) {
213-
// Should this be the aborted Error?
214-
throw new Error('Aborted');
215-
}
216-
217-
if (count === 0) {
218-
yield {
219-
explanation: 'answer',
220-
metadata: {},
221-
completed: true,
222-
};
223-
}
224-
225-
count++;
226-
}
227-
228190
const agent = new AiAgentMock({
229-
aidaClient: mockAidaClient(generateAndAnswer),
191+
aidaClient: mockAidaClient([[{
192+
explanation: 'answer',
193+
}]]),
230194
serverSideLoggingEnabled: true,
231195
});
232196

@@ -243,21 +207,15 @@ describeWithEnvironment('AiAgent', () => {
243207
describe('run', () => {
244208
describe('partial yielding for answers', () => {
245209
it('should yield partial answer with final answer at the end', async () => {
246-
async function* generateAnswerAfterPartial() {
247-
yield {
248-
explanation: 'Partial ans',
249-
metadata: {},
250-
completed: false,
251-
};
252-
253-
yield {
254-
explanation: 'Partial answer is now completed',
255-
metadata: {},
256-
completed: true,
257-
};
258-
}
259210
const agent = new AiAgentMock({
260-
aidaClient: mockAidaClient(generateAnswerAfterPartial),
211+
aidaClient: mockAidaClient([[
212+
{
213+
explanation: 'Partial ans',
214+
},
215+
{
216+
explanation: 'Partial answer is now completed',
217+
}
218+
]]),
261219
});
262220

263221
const responses = await Array.fromAsync(agent.run('query', {selected: mockConversationContext()}));
@@ -284,21 +242,15 @@ describeWithEnvironment('AiAgent', () => {
284242
});
285243

286244
it('should not add partial answers to history', async () => {
287-
async function* generateAnswerAfterPartial() {
288-
yield {
289-
explanation: 'Partial ans',
290-
metadata: {},
291-
completed: false,
292-
};
293-
294-
yield {
295-
explanation: 'Partial answer is now completed',
296-
metadata: {},
297-
completed: true,
298-
};
299-
}
300245
const agent = new AiAgentMock({
301-
aidaClient: mockAidaClient(generateAnswerAfterPartial),
246+
aidaClient: mockAidaClient([[
247+
{
248+
explanation: 'Partial ans',
249+
},
250+
{
251+
explanation: 'Partial answer is now completed',
252+
}
253+
]]),
302254
});
303255

304256
await Array.fromAsync(agent.run('query', {selected: mockConversationContext()}));
@@ -317,10 +269,8 @@ describeWithEnvironment('AiAgent', () => {
317269
});
318270

319271
it('should yield unknown error when aidaFetch does not return anything', async () => {
320-
async function* generateNothing() {
321-
}
322272
const agent = new AiAgentMock({
323-
aidaClient: mockAidaClient(generateNothing),
273+
aidaClient: mockAidaClient([]),
324274
});
325275

326276
const responses = await Array.fromAsync(agent.run('query', {selected: mockConversationContext()}));
@@ -343,27 +293,15 @@ describeWithEnvironment('AiAgent', () => {
343293

344294
describe('runFromHistory', () => {
345295
it('should run', async () => {
346-
let count = 0;
347-
async function* generateAndAnswer() {
348-
if (count === 0) {
349-
yield {
296+
const agent = new AiAgentMock({
297+
aidaClient: mockAidaClient([
298+
[{
350299
explanation: 'first answer',
351-
metadata: {},
352-
completed: true,
353-
};
354-
} else {
355-
yield {
300+
}],
301+
[{
356302
explanation: 'second answer',
357-
metadata: {},
358-
completed: true,
359-
};
360-
}
361-
362-
count++;
363-
}
364-
365-
const agent = new AiAgentMock({
366-
aidaClient: mockAidaClient(generateAndAnswer),
303+
}]
304+
]),
367305
serverSideLoggingEnabled: true,
368306
});
369307
await Array.fromAsync(agent.run('first question', {selected: null}));
@@ -495,7 +433,7 @@ describeWithEnvironment('AiAgent', () => {
495433

496434
it('should build a request with functions', () => {
497435
const agent = new AgentWithFunction({
498-
aidaClient: {} as Host.AidaClient.AidaClient,
436+
aidaClient: mockAidaClient(),
499437
});
500438
agent.options.temperature = -1;
501439
assert.deepEqual(

front_end/panels/ai_assistance/agents/FileAgent.test.ts

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import type * as Protocol from '../../../generated/protocol.js';
1010
import * as Bindings from '../../../models/bindings/bindings.js';
1111
import * as Logs from '../../../models/logs/logs.js';
1212
import * as Workspace from '../../../models/workspace/workspace.js';
13+
import {mockAidaClient} from '../../../testing/AiAssistanceHelpers.js';
1314
import {
1415
createTarget,
1516
getGetHostConfigStub,
@@ -31,15 +32,6 @@ describeWithMockConnection('FileAgent', () => {
3132
});
3233
}
3334

34-
function mockAidaClient(
35-
fetch: () => AsyncGenerator<Host.AidaClient.AidaResponse, void, void>,
36-
): Host.AidaClient.AidaClient {
37-
return {
38-
fetch,
39-
registerClientEvent: () => Promise.resolve({}),
40-
};
41-
}
42-
4335
beforeEach(() => {
4436
const workspace = Workspace.Workspace.WorkspaceImpl.instance();
4537
const targetManager = SDK.TargetManager.TargetManager.instance();
@@ -86,22 +78,8 @@ describeWithMockConnection('FileAgent', () => {
8678
it('structure matches the snapshot', async () => {
8779
mockHostConfig('test model');
8880
sinon.stub(crypto, 'randomUUID').returns('sessionId' as `${string}-${string}-${string}-${string}-${string}`);
89-
90-
let count = 0;
91-
async function* generateAndAnswer() {
92-
if (count === 0) {
93-
yield {
94-
explanation: 'answer',
95-
metadata: {},
96-
completed: true,
97-
};
98-
}
99-
100-
count++;
101-
}
102-
10381
const agent = new FileAgent({
104-
aidaClient: mockAidaClient(generateAndAnswer),
82+
aidaClient: mockAidaClient([[{explanation: 'answer'}]]),
10583
serverSideLoggingEnabled: true,
10684
});
10785
sinon.stub(agent, 'preamble').value('preamble');
@@ -228,18 +206,13 @@ describeWithMockConnection('FileAgent', () => {
228206

229207
testArguments.forEach(args => {
230208
it('generates an answer ' + args.name, async () => {
231-
async function* generateAnswer() {
232-
yield {
209+
const agent = new FileAgent({
210+
aidaClient: mockAidaClient([[{
233211
explanation: 'This is the answer',
234212
metadata: {
235213
rpcGlobalId: 123,
236214
},
237-
completed: true,
238-
};
239-
}
240-
241-
const agent = new FileAgent({
242-
aidaClient: mockAidaClient(generateAnswer),
215+
}]]),
243216
});
244217

245218
const uiSourceCode = await createUISourceCode({

front_end/panels/ai_assistance/agents/NetworkAgent.test.ts

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import * as Platform from '../../../core/platform/platform.js';
77
import * as SDK from '../../../core/sdk/sdk.js';
88
import type * as Protocol from '../../../generated/protocol.js';
99
import * as Logs from '../../../models/logs/logs.js';
10+
import {mockAidaClient} from '../../../testing/AiAssistanceHelpers.js';
1011
import {
1112
getGetHostConfigStub,
1213
} from '../../../testing/EnvironmentHelpers.js';
@@ -142,28 +143,14 @@ describeWithMockConnection('NetworkAgent', () => {
142143
sinon.restore();
143144
});
144145

145-
function mockAidaClient(
146-
fetch: () => AsyncGenerator<Host.AidaClient.AidaResponse, void, void>,
147-
): Host.AidaClient.AidaClient {
148-
return {
149-
fetch,
150-
registerClientEvent: () => Promise.resolve({}),
151-
};
152-
}
153-
154146
it('generates an answer', async () => {
155-
async function* generateAnswer() {
156-
yield {
147+
const agent = new NetworkAgent({
148+
aidaClient: mockAidaClient([[{
157149
explanation: 'This is the answer',
158150
metadata: {
159151
rpcGlobalId: 123,
160152
},
161-
completed: true,
162-
};
163-
}
164-
165-
const agent = new NetworkAgent({
166-
aidaClient: mockAidaClient(generateAnswer),
153+
}]]),
167154
});
168155

169156
const responses =

0 commit comments

Comments
 (0)