| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- //go:build unit
- package service
- import (
- "strings"
- "testing"
- "github.com/stretchr/testify/require"
- )
- // These tests guard against fmt.Sprintf arg-count mismatches in the email
- // templates. A mismatch would produce "%!(EXTRA ...)" or "%!v(MISSING)" in
- // the output, which these assertions will catch.
- // ---------- buildBalanceLowEmailBody ----------
- func TestBuildBalanceLowEmailBody_ContainsRequiredFields(t *testing.T) {
- s := &BalanceNotifyService{}
- body := s.buildBalanceLowEmailBody("Alice", 3.14, 10.0, "MySite", "")
- // All substituted values should appear in the output.
- require.Contains(t, body, "MySite")
- require.Contains(t, body, "Alice")
- require.Contains(t, body, "$3.14")
- require.Contains(t, body, "$10.00")
- // No fmt.Sprintf format error markers.
- require.NotContains(t, body, "%!")
- require.NotContains(t, body, "MISSING")
- require.NotContains(t, body, "EXTRA")
- }
- func TestBuildBalanceLowEmailBody_WithRechargeURL(t *testing.T) {
- s := &BalanceNotifyService{}
- body := s.buildBalanceLowEmailBody("Bob", 5.0, 20.0, "Site", "https://example.com/pay")
- // The recharge anchor element should appear with the URL.
- require.Contains(t, body, `href="https://example.com/pay"`)
- require.Contains(t, body, "立即充值")
- require.NotContains(t, body, "%!")
- }
- func TestBuildBalanceLowEmailBody_RechargeURLEscaped(t *testing.T) {
- s := &BalanceNotifyService{}
- // Try a URL with characters that need HTML escaping.
- body := s.buildBalanceLowEmailBody("u", 1.0, 5.0, "Site", `https://example.com/?a=1&b=<script>`)
- // `&` and `<` should be escaped in the href.
- require.Contains(t, body, "&")
- require.Contains(t, body, "<script>")
- require.NotContains(t, body, "<script>")
- }
- func TestBuildBalanceLowEmailBody_NoRechargeURLOmitsButton(t *testing.T) {
- s := &BalanceNotifyService{}
- body := s.buildBalanceLowEmailBody("u", 1.0, 5.0, "Site", "")
- // The anchor element should not be rendered (style class may still appear).
- require.NotContains(t, body, `<a href`)
- require.NotContains(t, body, "立即充值")
- }
- // ---------- buildQuotaAlertEmailBody ----------
- func TestBuildQuotaAlertEmailBody_AllFieldsPresent(t *testing.T) {
- s := &BalanceNotifyService{}
- body := s.buildQuotaAlertEmailBody(
- 42, // accountID
- "acc-foo", // accountName
- "anthropic", // platform
- "日限额 / Daily", // dimLabel
- 750.50, // used
- 1000.0, // limit
- 249.50, // remaining
- "$249.50", // thresholdDisplay
- "MySite", // siteName
- )
- require.Contains(t, body, "MySite")
- require.Contains(t, body, "#42")
- require.Contains(t, body, "acc-foo")
- require.Contains(t, body, "anthropic")
- require.Contains(t, body, "Daily")
- require.Contains(t, body, "$750.50")
- require.Contains(t, body, "$1000.00")
- require.Contains(t, body, "$249.50")
- // No format error markers.
- require.NotContains(t, body, "%!")
- require.NotContains(t, body, "MISSING")
- require.NotContains(t, body, "EXTRA")
- }
- func TestBuildQuotaAlertEmailBody_UnlimitedDisplay(t *testing.T) {
- s := &BalanceNotifyService{}
- body := s.buildQuotaAlertEmailBody(
- 1, "n", "p", "dim",
- 100.0, 0.0, // limit=0 triggers unlimited branch
- 0.0, "30%", "Site",
- )
- require.Contains(t, body, "无限制")
- require.Contains(t, body, "Unlimited")
- }
- func TestBuildQuotaAlertEmailBody_PercentageThresholdDisplay(t *testing.T) {
- s := &BalanceNotifyService{}
- body := s.buildQuotaAlertEmailBody(
- 1, "n", "p", "dim",
- 700.0, 1000.0, 300.0,
- "30%", // percentage-formatted threshold
- "Site",
- )
- require.Contains(t, body, "30%")
- require.NotContains(t, body, "%!")
- }
- func TestBuildQuotaAlertEmailBody_RemainingClampedAtZero(t *testing.T) {
- // Even though caller is responsible for clamping, this test documents the
- // display behavior with remaining=0.
- s := &BalanceNotifyService{}
- body := s.buildQuotaAlertEmailBody(
- 1, "n", "p", "dim",
- 1500.0, 1000.0, 0.0, // used > limit (over-quota)
- "$100.00", "Site",
- )
- require.Contains(t, body, "$0.00")
- }
- // ---------- sanity checks on the CSS `%%` escape ----------
- func TestBuildBalanceLowEmailBody_NoCSSFormatError(t *testing.T) {
- s := &BalanceNotifyService{}
- body := s.buildBalanceLowEmailBody("u", 1.0, 5.0, "Site", "")
- // CSS `linear-gradient(135deg, #f59e0b 0%, #d97706 100%)` should appear with
- // literal percent signs (from the %% escape in the template).
- require.True(t,
- strings.Contains(body, "0%") && strings.Contains(body, "100%"),
- "CSS gradient percentages not rendered; got: %s", body)
- }
- func TestBuildQuotaAlertEmailBody_NoCSSFormatError(t *testing.T) {
- s := &BalanceNotifyService{}
- body := s.buildQuotaAlertEmailBody(1, "n", "p", "d", 0, 0, 0, "$0.00", "Site")
- require.True(t,
- strings.Contains(body, "0%") && strings.Contains(body, "100%"),
- "CSS gradient percentages not rendered; got: %s", body)
- }
|