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

207 lines
7.0 KiB
TypeScript

/**
* @license
* Copyright 2026 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { makeFakeConfig } from '../test-utils/config.js';
import {
OverageMenuShownEvent,
OverageOptionSelectedEvent,
EmptyWalletMenuShownEvent,
CreditPurchaseClickEvent,
CreditsUsedEvent,
ApiKeyUpdatedEvent,
EVENT_OVERAGE_MENU_SHOWN,
EVENT_OVERAGE_OPTION_SELECTED,
EVENT_EMPTY_WALLET_MENU_SHOWN,
EVENT_CREDIT_PURCHASE_CLICK,
EVENT_CREDITS_USED,
EVENT_API_KEY_UPDATED,
} from './billingEvents.js';
describe('billingEvents', () => {
const fakeConfig = makeFakeConfig();
beforeEach(() => {
vi.useFakeTimers();
vi.setSystemTime(new Date('2026-01-15T10:30:00.000Z'));
});
afterEach(() => {
vi.useRealTimers();
});
describe('OverageMenuShownEvent', () => {
it('should construct with correct properties', () => {
const event = new OverageMenuShownEvent(
'gemini-3-pro-preview',
500,
'ask',
);
expect(event['event.name']).toBe('overage_menu_shown');
expect(event.model).toBe('gemini-3-pro-preview');
expect(event.credit_balance).toBe(500);
expect(event.overage_strategy).toBe('ask');
});
it('should produce correct OpenTelemetry attributes', () => {
const event = new OverageMenuShownEvent(
'gemini-3-pro-preview',
500,
'ask',
);
const attrs = event.toOpenTelemetryAttributes(fakeConfig);
expect(attrs['event.name']).toBe(EVENT_OVERAGE_MENU_SHOWN);
expect(attrs['model']).toBe('gemini-3-pro-preview');
expect(attrs['credit_balance']).toBe(500);
expect(attrs['overage_strategy']).toBe('ask');
});
it('should produce a human-readable log body', () => {
const event = new OverageMenuShownEvent(
'gemini-3-pro-preview',
500,
'ask',
);
expect(event.toLogBody()).toContain('gemini-3-pro-preview');
expect(event.toLogBody()).toContain('500');
});
});
describe('OverageOptionSelectedEvent', () => {
it('should construct with correct properties', () => {
const event = new OverageOptionSelectedEvent(
'gemini-3-pro-preview',
'use_credits',
100,
);
expect(event['event.name']).toBe('overage_option_selected');
expect(event.selected_option).toBe('use_credits');
expect(event.credit_balance).toBe(100);
});
it('should produce correct OpenTelemetry attributes', () => {
const event = new OverageOptionSelectedEvent(
'gemini-3-pro-preview',
'use_fallback',
200,
);
const attrs = event.toOpenTelemetryAttributes(fakeConfig);
expect(attrs['event.name']).toBe(EVENT_OVERAGE_OPTION_SELECTED);
expect(attrs['selected_option']).toBe('use_fallback');
});
it('should produce a human-readable log body', () => {
const event = new OverageOptionSelectedEvent(
'gemini-3-pro-preview',
'manage',
100,
);
expect(event.toLogBody()).toContain('manage');
expect(event.toLogBody()).toContain('gemini-3-pro-preview');
});
});
describe('EmptyWalletMenuShownEvent', () => {
it('should construct with correct properties', () => {
const event = new EmptyWalletMenuShownEvent('gemini-3-pro-preview');
expect(event['event.name']).toBe('empty_wallet_menu_shown');
expect(event.model).toBe('gemini-3-pro-preview');
});
it('should produce correct OpenTelemetry attributes', () => {
const event = new EmptyWalletMenuShownEvent('gemini-3-pro-preview');
const attrs = event.toOpenTelemetryAttributes(fakeConfig);
expect(attrs['event.name']).toBe(EVENT_EMPTY_WALLET_MENU_SHOWN);
expect(attrs['model']).toBe('gemini-3-pro-preview');
});
it('should produce a human-readable log body', () => {
const event = new EmptyWalletMenuShownEvent('gemini-3-pro-preview');
expect(event.toLogBody()).toContain('gemini-3-pro-preview');
});
});
describe('CreditPurchaseClickEvent', () => {
it('should construct with correct properties', () => {
const event = new CreditPurchaseClickEvent(
'empty_wallet_menu',
'gemini-3-pro-preview',
);
expect(event['event.name']).toBe('credit_purchase_click');
expect(event.source).toBe('empty_wallet_menu');
expect(event.model).toBe('gemini-3-pro-preview');
});
it('should produce correct OpenTelemetry attributes', () => {
const event = new CreditPurchaseClickEvent(
'overage_menu',
'gemini-3-pro-preview',
);
const attrs = event.toOpenTelemetryAttributes(fakeConfig);
expect(attrs['event.name']).toBe(EVENT_CREDIT_PURCHASE_CLICK);
expect(attrs['source']).toBe('overage_menu');
});
it('should produce a human-readable log body', () => {
const event = new CreditPurchaseClickEvent(
'manage',
'gemini-3-pro-preview',
);
expect(event.toLogBody()).toContain('manage');
expect(event.toLogBody()).toContain('gemini-3-pro-preview');
});
});
describe('CreditsUsedEvent', () => {
it('should construct with correct properties', () => {
const event = new CreditsUsedEvent('gemini-3-pro-preview', 10, 490);
expect(event['event.name']).toBe('credits_used');
expect(event.credits_consumed).toBe(10);
expect(event.credits_remaining).toBe(490);
});
it('should produce correct OpenTelemetry attributes', () => {
const event = new CreditsUsedEvent('gemini-3-pro-preview', 10, 490);
const attrs = event.toOpenTelemetryAttributes(fakeConfig);
expect(attrs['event.name']).toBe(EVENT_CREDITS_USED);
expect(attrs['credits_consumed']).toBe(10);
expect(attrs['credits_remaining']).toBe(490);
});
it('should produce a human-readable log body', () => {
const event = new CreditsUsedEvent('gemini-3-pro-preview', 10, 490);
const body = event.toLogBody();
expect(body).toContain('10');
expect(body).toContain('490');
expect(body).toContain('gemini-3-pro-preview');
});
});
describe('ApiKeyUpdatedEvent', () => {
it('should construct with correct properties', () => {
const event = new ApiKeyUpdatedEvent('google_login', 'api_key');
expect(event['event.name']).toBe('api_key_updated');
expect(event.previous_auth_type).toBe('google_login');
expect(event.new_auth_type).toBe('api_key');
});
it('should produce correct OpenTelemetry attributes', () => {
const event = new ApiKeyUpdatedEvent('google_login', 'api_key');
const attrs = event.toOpenTelemetryAttributes(fakeConfig);
expect(attrs['event.name']).toBe(EVENT_API_KEY_UPDATED);
expect(attrs['previous_auth_type']).toBe('google_login');
expect(attrs['new_auth_type']).toBe('api_key');
});
it('should produce a human-readable log body', () => {
const event = new ApiKeyUpdatedEvent('google_login', 'api_key');
const body = event.toLogBody();
expect(body).toContain('google_login');
expect(body).toContain('api_key');
});
});
});