feat: add rich token message renderer with conditional rows
Introduce unified rich token message rendering with fixed row order and conditional visibility based on available sources. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
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:")
|
||||
}
|
||||
Reference in New Issue
Block a user