using ClaudeDo.Worker.Usage.TokenTracker; using ClaudeDo.Worker.Usage.TokenTracker.Interfaces; namespace ClaudeDo.Worker.Tests.Usage.TokenTracker; public sealed class FakeTokenTrackerClient : ITokenTrackerClient { private readonly SemaphoreSlim _gate = new(0); public TokenTrackerProbe Probe { get; set; } = new(true, "1.2.3", true, "v22.1.0", null); public TokenTrackerRunResult ExportResult { get; set; } = new(true, TokenTrackerFixtures.SessionsJson, null); public TokenTrackerRunResult InstallResult { get; set; } = new(true, "added 1 package", null); public int ExportCalls; public int ProbeCalls; public int InstallCalls; public DateOnly? LastFrom; public DateOnly? LastTo; /// When true, blocks until is called. public bool BlockExport { get; set; } public void Release() => _gate.Release(); public Task ProbeAsync(CancellationToken ct = default) { Interlocked.Increment(ref ProbeCalls); return Task.FromResult(Probe); } public async Task ExportAsync(DateOnly from, DateOnly to, CancellationToken ct = default) { Interlocked.Increment(ref ExportCalls); LastFrom = from; LastTo = to; if (BlockExport) await _gate.WaitAsync(ct); return ExportResult; } public TokenTrackerDashboard DashboardResult { get; set; } = new(true, "http://127.0.0.1:7680/", null); public int DashboardCalls; public Task StartDashboardAsync(CancellationToken ct = default) { Interlocked.Increment(ref DashboardCalls); return Task.FromResult(DashboardResult); } public Task InstallAsync(IProgress? output = null, CancellationToken ct = default) { Interlocked.Increment(ref InstallCalls); output?.Report("added 1 package"); return Task.FromResult(InstallResult); } }