Files
telemetry-client-js/tests/event-builder.test.ts
Jason Woltje 493bc72601
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
chore(#1): apply Prettier formatting to all source and test files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 22:48:08 -06:00

224 lines
6.5 KiB
TypeScript

import { describe, it, expect, vi, afterEach } from "vitest";
import { EventBuilder } from "../src/event-builder.js";
import { ResolvedConfig } from "../src/config.js";
import {
TaskType,
Complexity,
Harness,
Provider,
Outcome,
QualityGate,
RepoSizeCategory,
} from "../src/types/events.js";
function makeConfig(): ResolvedConfig {
return {
serverUrl: "https://tel.example.com",
apiKey: "a".repeat(64),
instanceId: "my-instance-uuid",
enabled: true,
submitIntervalMs: 300_000,
maxQueueSize: 1000,
batchSize: 100,
requestTimeoutMs: 10_000,
predictionCacheTtlMs: 21_600_000,
dryRun: false,
maxRetries: 3,
onError: () => {},
};
}
describe("EventBuilder", () => {
afterEach(() => {
vi.restoreAllMocks();
});
it("should build a complete TaskCompletionEvent", () => {
const builder = new EventBuilder(makeConfig());
const event = builder.build({
task_duration_ms: 15000,
task_type: TaskType.IMPLEMENTATION,
complexity: Complexity.HIGH,
harness: Harness.CLAUDE_CODE,
model: "claude-3-opus",
provider: Provider.ANTHROPIC,
estimated_input_tokens: 2000,
estimated_output_tokens: 1000,
actual_input_tokens: 2200,
actual_output_tokens: 1100,
estimated_cost_usd_micros: 100000,
actual_cost_usd_micros: 110000,
quality_gate_passed: true,
quality_gates_run: [
QualityGate.BUILD,
QualityGate.TEST,
QualityGate.LINT,
],
quality_gates_failed: [],
context_compactions: 2,
context_rotations: 1,
context_utilization_final: 0.75,
outcome: Outcome.SUCCESS,
retry_count: 0,
language: "typescript",
repo_size_category: RepoSizeCategory.MEDIUM,
});
expect(event.task_type).toBe(TaskType.IMPLEMENTATION);
expect(event.complexity).toBe(Complexity.HIGH);
expect(event.model).toBe("claude-3-opus");
expect(event.quality_gates_run).toEqual([
QualityGate.BUILD,
QualityGate.TEST,
QualityGate.LINT,
]);
expect(event.language).toBe("typescript");
expect(event.repo_size_category).toBe(RepoSizeCategory.MEDIUM);
});
it("should auto-generate event_id as UUID", () => {
const builder = new EventBuilder(makeConfig());
const event = builder.build({
task_duration_ms: 1000,
task_type: TaskType.TESTING,
complexity: Complexity.LOW,
harness: Harness.AIDER,
model: "gpt-4",
provider: Provider.OPENAI,
estimated_input_tokens: 100,
estimated_output_tokens: 50,
actual_input_tokens: 100,
actual_output_tokens: 50,
estimated_cost_usd_micros: 1000,
actual_cost_usd_micros: 1000,
quality_gate_passed: true,
quality_gates_run: [],
quality_gates_failed: [],
context_compactions: 0,
context_rotations: 0,
context_utilization_final: 0.3,
outcome: Outcome.SUCCESS,
retry_count: 0,
});
// UUID format: 8-4-4-4-12 hex chars
expect(event.event_id).toMatch(
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,
);
// Each event should get a unique ID
const event2 = builder.build({
task_duration_ms: 1000,
task_type: TaskType.TESTING,
complexity: Complexity.LOW,
harness: Harness.AIDER,
model: "gpt-4",
provider: Provider.OPENAI,
estimated_input_tokens: 100,
estimated_output_tokens: 50,
actual_input_tokens: 100,
actual_output_tokens: 50,
estimated_cost_usd_micros: 1000,
actual_cost_usd_micros: 1000,
quality_gate_passed: true,
quality_gates_run: [],
quality_gates_failed: [],
context_compactions: 0,
context_rotations: 0,
context_utilization_final: 0.3,
outcome: Outcome.SUCCESS,
retry_count: 0,
});
expect(event.event_id).not.toBe(event2.event_id);
});
it("should auto-set timestamp to ISO 8601", () => {
const now = new Date("2026-02-07T10:00:00.000Z");
vi.setSystemTime(now);
const builder = new EventBuilder(makeConfig());
const event = builder.build({
task_duration_ms: 1000,
task_type: TaskType.DEBUGGING,
complexity: Complexity.MEDIUM,
harness: Harness.OPENCODE,
model: "claude-3-sonnet",
provider: Provider.ANTHROPIC,
estimated_input_tokens: 500,
estimated_output_tokens: 200,
actual_input_tokens: 500,
actual_output_tokens: 200,
estimated_cost_usd_micros: 5000,
actual_cost_usd_micros: 5000,
quality_gate_passed: false,
quality_gates_run: [QualityGate.TEST],
quality_gates_failed: [QualityGate.TEST],
context_compactions: 0,
context_rotations: 0,
context_utilization_final: 0.4,
outcome: Outcome.FAILURE,
retry_count: 1,
});
expect(event.timestamp).toBe("2026-02-07T10:00:00.000Z");
});
it("should set instance_id from config", () => {
const config = makeConfig();
const builder = new EventBuilder(config);
const event = builder.build({
task_duration_ms: 1000,
task_type: TaskType.PLANNING,
complexity: Complexity.LOW,
harness: Harness.UNKNOWN,
model: "test-model",
provider: Provider.UNKNOWN,
estimated_input_tokens: 0,
estimated_output_tokens: 0,
actual_input_tokens: 0,
actual_output_tokens: 0,
estimated_cost_usd_micros: 0,
actual_cost_usd_micros: 0,
quality_gate_passed: true,
quality_gates_run: [],
quality_gates_failed: [],
context_compactions: 0,
context_rotations: 0,
context_utilization_final: 0,
outcome: Outcome.SUCCESS,
retry_count: 0,
});
expect(event.instance_id).toBe("my-instance-uuid");
});
it("should set schema_version to 1.0", () => {
const builder = new EventBuilder(makeConfig());
const event = builder.build({
task_duration_ms: 1000,
task_type: TaskType.REFACTORING,
complexity: Complexity.CRITICAL,
harness: Harness.KILO_CODE,
model: "gemini-pro",
provider: Provider.GOOGLE,
estimated_input_tokens: 3000,
estimated_output_tokens: 2000,
actual_input_tokens: 3000,
actual_output_tokens: 2000,
estimated_cost_usd_micros: 80000,
actual_cost_usd_micros: 80000,
quality_gate_passed: true,
quality_gates_run: [QualityGate.TYPECHECK],
quality_gates_failed: [],
context_compactions: 5,
context_rotations: 2,
context_utilization_final: 0.95,
outcome: Outcome.SUCCESS,
retry_count: 0,
});
expect(event.schema_version).toBe("1.0");
});
});