Files
gemini-cli/packages/core/src/code_assist/telemetry.test.ts

163 lines
4.3 KiB
TypeScript
Raw Normal View History

2025-12-16 09:34:05 -08:00
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { describe, it, expect, vi } from 'vitest';
import {
createConversationOffered,
formatProtoJsonDuration,
} from './telemetry.js';
import { ActionStatus, type StreamingLatency } from './types.js';
import { FinishReason, GenerateContentResponse } from '@google/genai';
function createMockResponse(
candidates: GenerateContentResponse['candidates'] = [],
ok = true,
) {
const response = new GenerateContentResponse();
response.candidates = candidates;
response.sdkHttpResponse = {
responseInternal: {
ok,
} as unknown as Response,
json: async () => ({}),
};
return response;
}
describe('telemetry', () => {
describe('createConversationOffered', () => {
it('should create a ConversationOffered object with correct values', () => {
const response = createMockResponse([
{
index: 0,
content: {
role: 'model',
parts: [{ text: 'response with ```code```' }],
},
citationMetadata: {
citations: [
{ uri: 'https://example.com', startIndex: 0, endIndex: 10 },
],
},
finishReason: FinishReason.STOP,
},
]);
const traceId = 'test-trace-id';
const streamingLatency: StreamingLatency = { totalLatency: '1s' };
const result = createConversationOffered(
response,
traceId,
undefined,
streamingLatency,
);
expect(result).toEqual({
citationCount: '1',
includedCode: true,
status: ActionStatus.ACTION_STATUS_NO_ERROR,
traceId,
streamingLatency,
isAgentic: true,
});
});
it('should set status to CANCELLED if signal is aborted', () => {
const response = createMockResponse();
const signal = new AbortController().signal;
vi.spyOn(signal, 'aborted', 'get').mockReturnValue(true);
const result = createConversationOffered(
response,
'trace-id',
signal,
{},
);
expect(result.status).toBe(ActionStatus.ACTION_STATUS_CANCELLED);
});
it('should set status to ERROR_UNKNOWN if response has error (non-OK SDK response)', () => {
const response = createMockResponse([], false);
const result = createConversationOffered(
response,
'trace-id',
undefined,
{},
);
expect(result.status).toBe(ActionStatus.ACTION_STATUS_ERROR_UNKNOWN);
});
it('should set status to ERROR_UNKNOWN if finishReason is not STOP or MAX_TOKENS', () => {
const response = createMockResponse([
{
index: 0,
finishReason: FinishReason.SAFETY,
},
]);
const result = createConversationOffered(
response,
'trace-id',
undefined,
{},
);
expect(result.status).toBe(ActionStatus.ACTION_STATUS_ERROR_UNKNOWN);
});
it('should set status to EMPTY if candidates is empty', () => {
const response = createMockResponse();
const result = createConversationOffered(
response,
'trace-id',
undefined,
{},
);
expect(result.status).toBe(ActionStatus.ACTION_STATUS_EMPTY);
});
it('should detect code in response', () => {
const response = createMockResponse([
{
index: 0,
content: {
parts: [
{ text: 'Here is some code:\n```js\nconsole.log("hi")\n```' },
],
},
},
]);
const result = createConversationOffered(response, 'id', undefined, {});
expect(result.includedCode).toBe(true);
});
it('should not detect code if no backticks', () => {
const response = createMockResponse([
{
index: 0,
content: {
parts: [{ text: 'Here is some text.' }],
},
},
]);
const result = createConversationOffered(response, 'id', undefined, {});
expect(result.includedCode).toBe(false);
});
});
describe('formatProtoJsonDuration', () => {
it('should format milliseconds to seconds string', () => {
expect(formatProtoJsonDuration(1500)).toBe('1.5s');
expect(formatProtoJsonDuration(100)).toBe('0.1s');
});
});
});