package view import ( "strings" "testing" ) func assertContainsAll(t *testing.T, msg string, rows ...string) { t.Helper() for _, r := range rows { if !strings.Contains(msg, r) { t.Fatalf("expected row %q in message:\n%s", r, msg) } } } func assertContainsNone(t *testing.T, msg string, rows ...string) { t.Helper() for _, r := range rows { if strings.Contains(msg, r) { t.Fatalf("unexpected row %q in message:\n%s", r, msg) } } } func TestRenderRichTokenMessage_AllSources(t *testing.T) { msg := RenderRichTokenMessage(RichTokenMessageInput{ Token: "ETH", HasSpot: true, SpotPrice: 3245, HasFuture: true, FuturePrice: 3251, FundingRate: 0.000123, FundingTimeMs: 1740000000000, HasAlpha: true, AlphaPrice: 3248, HasAlpha24h: true, Alpha24hChange: -3.21, HasMarginAPR: true, MarginAPRPercent: 7.665, }) expectedOrder := []string{ "🪙 ETH", "💵 Spot:", "📈 Future:", "🅰️ Alpha:", "🧭 Basis:", "💸 Funding:", "🏦 Margin:", "📊 Alpha 24h:", } last := -1 for _, part := range expectedOrder { i := strings.Index(msg, part) if i == -1 { t.Fatalf("missing row %q in message:\n%s", part, msg) } if i < last { t.Fatalf("row %q appears out of order in message:\n%s", part, msg) } last = i } } func TestRenderRichTokenMessage_FutureOnly(t *testing.T) { msg := RenderRichTokenMessage(RichTokenMessageInput{ Token: "ABC", HasFuture: true, FuturePrice: 1234, FundingRate: 0.000081, FundingTimeMs: 1740000000000, HasMarginAPR: true, MarginAPRPercent: 6.2, }) assertContainsAll(t, msg, "🪙 ABC", "📈 Future:", "💸 Funding:", "🏦 Margin:") assertContainsNone(t, msg, "💵 Spot:", "🅰️ Alpha:", "🧭 Basis:", "📊 Alpha 24h:") } func TestRenderRichTokenMessage_SpotOnly(t *testing.T) { msg := RenderRichTokenMessage(RichTokenMessageInput{ Token: "XRP", HasSpot: true, SpotPrice: 2.1, HasMarginAPR: true, MarginAPRPercent: 5.11, }) assertContainsAll(t, msg, "🪙 XRP", "💵 Spot:", "🏦 Margin:") assertContainsNone(t, msg, "📈 Future:", "🅰️ Alpha:", "🧭 Basis:", "💸 Funding:", "📊 Alpha 24h:") } func TestRenderRichTokenMessage_AlphaOnly(t *testing.T) { msg := RenderRichTokenMessage(RichTokenMessageInput{ Token: "ABC", HasAlpha: true, AlphaPrice: 0.1234, HasAlpha24h: true, Alpha24hChange: 12.4, }) assertContainsAll(t, msg, "🪙 ABC", "🅰️ Alpha:", "📊 Alpha 24h:") assertContainsNone(t, msg, "💵 Spot:", "📈 Future:", "🧭 Basis:", "💸 Funding:", "🏦 Margin:") } func TestRenderRichTokenMessage_SpotAndFuture(t *testing.T) { msg := RenderRichTokenMessage(RichTokenMessageInput{ Token: "SOL", HasSpot: true, SpotPrice: 182.4, HasFuture: true, FuturePrice: 183.0, FundingRate: -0.000041, FundingTimeMs: 1740000000000, HasMarginAPR: true, MarginAPRPercent: 5.11, }) assertContainsAll(t, msg, "🪙 SOL", "💵 Spot:", "📈 Future:", "🧭 Basis:", "💸 Funding:", "🏦 Margin:") assertContainsNone(t, msg, "🅰️ Alpha:", "📊 Alpha 24h:") }