Skip to content

Commit

Permalink
feat: export test formatters
Browse files Browse the repository at this point in the history
  • Loading branch information
mdonnalley committed Dec 4, 2024
1 parent ac30992 commit b5f26df
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 37 deletions.
30 changes: 9 additions & 21 deletions src/agentTester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import { Connection, Lifecycle, PollingClient, StatusResult } from '@salesforce/
import { Duration } from '@salesforce/kit';
import { MaybeMock } from './maybe-mock';

type Format = 'human' | 'json';

export type TestStatus = 'NEW' | 'IN_PROGRESS' | 'COMPLETED' | 'ERROR';

export type AgentTestStartResponse = {
Expand Down Expand Up @@ -91,25 +89,22 @@ export class AgentTester {
public async poll(
jobId: string,
{
format = 'human',
timeout = Duration.minutes(5),
}: {
format?: Format;
timeout?: Duration;
} = {
format: 'human',
timeout: Duration.minutes(5),
}
): Promise<{ response: AgentTestDetailsResponse; formatted: string }> {
): Promise<AgentTestDetailsResponse> {
const lifecycle = Lifecycle.getInstance();
const client = await PollingClient.create({
poll: async (): Promise<StatusResult> => {
// NOTE: we don't actually need to call the status API here since all the same information is present on the
// details API. We could just call the details API and check the status there.
const [detailsResponse, statusResponse] = await Promise.all([this.details(jobId, format), this.status(jobId)]);
const totalTestCases = detailsResponse.response.testCases.length;
const failingTestCases = detailsResponse.response.testCases.filter((tc) => tc.status === 'ERROR').length;
const passingTestCases = detailsResponse.response.testCases.filter(
const [detailsResponse, statusResponse] = await Promise.all([this.details(jobId), this.status(jobId)]);
const totalTestCases = detailsResponse.testCases.length;
const failingTestCases = detailsResponse.testCases.filter((tc) => tc.status === 'ERROR').length;
const passingTestCases = detailsResponse.testCases.filter(
(tc) => tc.status === 'COMPLETED' && tc.expectationResults.every((r) => r.result === 'Passed')
).length;

Expand All @@ -121,7 +116,7 @@ export class AgentTester {
failingTestCases,
passingTestCases,
});
return { payload: await this.details(jobId, format), completed: true };
return { payload: detailsResponse, completed: true };
}

await lifecycle.emit('AGENT_TEST_POLLING_EVENT', {
Expand All @@ -137,21 +132,14 @@ export class AgentTester {
timeout,
});

const result = await client.subscribe<{ response: AgentTestDetailsResponse; formatted: string }>();
const result = await client.subscribe<AgentTestDetailsResponse>();
return result;
}

public async details(
jobId: string,
format: Format = 'human'
): Promise<{ response: AgentTestDetailsResponse; formatted: string }> {
public async details(jobId: string): Promise<AgentTestDetailsResponse> {
const url = `/einstein/ai-evaluations/runs/${jobId}/details`;

const response = await this.maybeMock.request<AgentTestDetailsResponse>('GET', url);
return {
response,
formatted: format === 'human' ? await humanFormat(jobId, response) : await jsonFormat(response),
};
return this.maybeMock.request<AgentTestDetailsResponse>('GET', url);
}

public async cancel(jobId: string): Promise<{ success: boolean }> {
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export {
export { Agent } from './agent';
export {
AgentTester,
humanFormat,
jsonFormat,
type AgentTestDetailsResponse,
type AgentTestStartResponse,
type AgentTestStatusResponse,
Expand Down
20 changes: 4 additions & 16 deletions test/agentTester.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,25 +51,13 @@ describe('AgentTester', () => {
});

describe('poll', () => {
it('should poll until test run is complete (human format)', async () => {
it('should poll until test run is complete', async () => {
const tester = new AgentTester(connection);
await tester.start('suiteId');
const output = await tester.poll('4KBSM000000003F4AQ');
expect(output).to.be.ok;
// TODO: make these assertions more meaningful
expect(output.formatted).to.include('Test Case #1');
expect(output.formatted).to.include('Test Case #2');
expect(output.response.testCases[0].status).to.equal('COMPLETED');
});

it('should poll until test run is complete (json format)', async () => {
const tester = new AgentTester(connection);
await tester.start('suiteId');
const output = await tester.poll('4KBSM000000003F4AQ', { format: 'json' });
expect(output).to.be.ok;
const response = await tester.poll('4KBSM000000003F4AQ');
expect(response).to.be.ok;
// TODO: make these assertions more meaningful
expect(JSON.parse(output.formatted)).to.deep.equal(output.response);
expect(output.response.testCases[0].status).to.equal('COMPLETED');
expect(response.testCases[0].status).to.equal('COMPLETED');
});
});

Expand Down

0 comments on commit b5f26df

Please sign in to comment.