f99010fae1
CI / lint (push) Failing after 1s
CI / frontend (push) Failing after 1s
CI / scripts (push) Failing after 1s
CI / Go Test (ubuntu-latest) (push) Failing after 0s
CI / frontend-node-25 (push) Failing after 1s
CI / docs (push) Failing after 0s
CI / coverage (push) Failing after 0s
CI / e2e (push) Failing after 0s
Docker / build-and-push (push) Failing after 1s
CI / integration (push) Failing after 4m43s
CI / Go Test (windows-latest) (push) Has been cancelled
CI / Desktop Unit Tests (Windows) (push) Has been cancelled
Desktop Artifacts / Desktop Build (Linux (arm64)) (push) Has been cancelled
Desktop Artifacts / Desktop Build (Linux) (push) Has been cancelled
Desktop Artifacts / Desktop Build (Windows) (push) Has been cancelled
Desktop Artifacts (macOS) / Desktop Build (macOS (aarch64)) (push) Has been cancelled
Desktop Artifacts (macOS) / Desktop Build (macOS (x86_64)) (push) Has been cancelled
161 lines
4.7 KiB
Go
161 lines
4.7 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"go.kenn.io/agentsview/internal/db"
|
|
)
|
|
|
|
func TestRenderSessionUsageHuman_WithCost(t *testing.T) {
|
|
out := &sessionUsageOutput{
|
|
SessionUsage: db.SessionUsage{
|
|
SessionID: "claude:s1", Agent: "claude-code", Project: "proj",
|
|
TotalOutputTokens: 28800, PeakContextTokens: 118000,
|
|
HasTokenData: true, CostUSD: 0.42, HasCost: true,
|
|
Models: []string{"claude-opus-4-6"},
|
|
},
|
|
}
|
|
var b strings.Builder
|
|
require.NoError(t, renderSessionUsageHuman(&b, out))
|
|
s := b.String()
|
|
assert.Contains(t, s, "~$0.42", "output missing cost")
|
|
assert.Contains(t, s, "claude-opus-4-6", "output missing model")
|
|
}
|
|
|
|
func TestRenderSessionUsageHuman_NoCostNoModels(t *testing.T) {
|
|
out := &sessionUsageOutput{
|
|
SessionUsage: db.SessionUsage{
|
|
SessionID: "claude:s3", Agent: "claude-code",
|
|
HasTokenData: true, HasCost: false,
|
|
},
|
|
}
|
|
var b strings.Builder
|
|
require.NoError(t, renderSessionUsageHuman(&b, out))
|
|
s := b.String()
|
|
assert.Contains(t, s, "n/a", "expected bare 'n/a' cost line")
|
|
assert.NotContains(t, s, "unpriced",
|
|
"should not mention unpriced when none")
|
|
}
|
|
|
|
func TestRenderSessionUsageHuman_NoCost(t *testing.T) {
|
|
out := &sessionUsageOutput{
|
|
SessionUsage: db.SessionUsage{
|
|
SessionID: "claude:s2", Agent: "claude-code",
|
|
HasTokenData: true, HasCost: false,
|
|
UnpricedModels: []string{"local-llama-99"},
|
|
},
|
|
}
|
|
var b strings.Builder
|
|
require.NoError(t, renderSessionUsageHuman(&b, out))
|
|
s := b.String()
|
|
assert.NotContains(t, s, "$", "no-cost output should not contain '$'")
|
|
assert.Contains(t, s, "local-llama-99",
|
|
"output should note unpriced model")
|
|
}
|
|
|
|
func TestRenderSessionUsageHuman_CopilotWithAICredits(t *testing.T) {
|
|
out := &sessionUsageOutput{
|
|
SessionUsage: db.SessionUsage{
|
|
SessionID: "copilot:s1",
|
|
Agent: "copilot",
|
|
Project: "proj",
|
|
TotalOutputTokens: 2000,
|
|
PeakContextTokens: 5000,
|
|
HasTokenData: true,
|
|
CostUSD: 10.00,
|
|
HasCost: true,
|
|
AICredits: 1000.0,
|
|
Models: []string{"gpt-4"},
|
|
},
|
|
}
|
|
var b strings.Builder
|
|
require.NoError(t, renderSessionUsageHuman(&b, out))
|
|
s := b.String()
|
|
assert.Contains(t, s, "~$10.00", "output missing cost")
|
|
assert.Contains(t, s, "1000", "output missing AI Credits")
|
|
assert.Contains(t, s, "AI Credits", "output missing AI Credits label")
|
|
}
|
|
|
|
func TestRenderSessionUsageHuman_NonCopilotNoAICredits(t *testing.T) {
|
|
out := &sessionUsageOutput{
|
|
SessionUsage: db.SessionUsage{
|
|
SessionID: "claude:s1",
|
|
Agent: "claude-code",
|
|
Project: "proj",
|
|
TotalOutputTokens: 1000,
|
|
PeakContextTokens: 5000,
|
|
HasTokenData: true,
|
|
CostUSD: 0.42,
|
|
HasCost: true,
|
|
Models: []string{"claude-opus"},
|
|
},
|
|
}
|
|
var b strings.Builder
|
|
require.NoError(t, renderSessionUsageHuman(&b, out))
|
|
s := b.String()
|
|
assert.Contains(t, s, "~$0.42", "output missing cost")
|
|
assert.NotContains(t, s, "AI Credits",
|
|
"non-Copilot sessions should not show AI Credits")
|
|
}
|
|
|
|
func TestRenderSessionUsageHuman_CopilotNoCost(t *testing.T) {
|
|
out := &sessionUsageOutput{
|
|
SessionUsage: db.SessionUsage{
|
|
SessionID: "copilot:s2",
|
|
Agent: "copilot",
|
|
HasTokenData: true,
|
|
HasCost: false,
|
|
AICredits: 0,
|
|
UnpricedModels: []string{"gpt-4"},
|
|
},
|
|
}
|
|
var b strings.Builder
|
|
require.NoError(t, renderSessionUsageHuman(&b, out))
|
|
s := b.String()
|
|
assert.NotContains(t, s, "AI Credits",
|
|
"unpriced Copilot sessions should not show AI Credits")
|
|
}
|
|
|
|
func TestSessionUsageJSONSchemaIncludesCostContract(t *testing.T) {
|
|
out := &sessionUsageOutput{
|
|
SessionUsage: db.SessionUsage{
|
|
SessionID: "codex:abc",
|
|
Agent: "codex",
|
|
Project: "my-project",
|
|
TotalOutputTokens: 123,
|
|
PeakContextTokens: 456,
|
|
HasTokenData: true,
|
|
CostUSD: 0.42,
|
|
HasCost: true,
|
|
Models: []string{"gpt-5.1"},
|
|
UnpricedModels: []string{"local-model"},
|
|
},
|
|
ServerRunning: true,
|
|
}
|
|
|
|
data, err := json.Marshal(out)
|
|
require.NoError(t, err)
|
|
|
|
var raw map[string]any
|
|
require.NoError(t, json.Unmarshal(data, &raw))
|
|
assert.Equal(t, map[string]any{
|
|
"session_id": "codex:abc",
|
|
"agent": "codex",
|
|
"project": "my-project",
|
|
"breakdown_count": float64(0),
|
|
"breakdown": nil,
|
|
"total_output_tokens": float64(123),
|
|
"peak_context_tokens": float64(456),
|
|
"has_token_data": true,
|
|
"cost_usd": 0.42,
|
|
"has_cost": true,
|
|
"models": []any{"gpt-5.1"},
|
|
"unpriced_models": []any{"local-model"},
|
|
"server_running": true,
|
|
}, raw)
|
|
}
|