package render import ( "strings" "testing" "git.5iot.com/iotlcm-public/iotlcm-bot/internal/archive" ) func sample() archive.RunArchive { return archive.RunArchive{Version: 1, Run: archive.RunSummary{RunID: "run-1", Operation: "sim_status_queue_full_sync", Status: "completed_with_failures", SuccessCount: 175893, FailedCount: 10504, CreatedAt: "2026-09-22T11:42:33Z", CompletedAt: "2026-09-22T12:32:01Z"}, Rounds: []archive.RoundStats{ {Round: 1, EnqueuedCount: 186397, NextRoundCount: 9023, SuccessCount: 175870, FailedCount: 1504, StartedAt: "2026-09-22T11:42:34Z", CompletedAt: "2026-09-22T12:21:49Z"}, {Round: 2, EnqueuedCount: 9023, NextRoundCount: 9000, SuccessCount: 23, FailedCount: 0, StartedAt: "2026-09-22T12:21:51Z", CompletedAt: "2026-09-22T12:26:55Z"}, {Round: 3, EnqueuedCount: 9000, NextRoundCount: 0, SuccessCount: 0, FailedCount: 9000, StartedAt: "2026-09-22T12:26:56Z", CompletedAt: "2026-09-22T12:32:01Z"}, }} } func TestKindNamesEachSyncType(t *testing.T) { cases := []struct{ operation, want string }{ {"previous_day_usage_full_sync", "日流量同步"}, {"previous_month_usage_full_sync", "月历史同步"}, {"current_month_usage_full_sync", "本月流量快照同步"}, {"sim_status_queue_full_sync", "卡状态全量同步"}, {"traffic_usage_full_sync", "流量全量同步"}, {"usage_full_sync", "流量全量同步"}, {"imei_full_sync", "imei_full_sync"}, } for _, c := range cases { if got := Kind(c.operation); got != c.want { t.Errorf("Kind(%q) = %q, want %q", c.operation, got, c.want) } } } func TestKindKeepsTrafficSyncTitlesDistinct(t *testing.T) { seen := map[string]string{} for _, operation := range []string{"previous_day_usage_full_sync", "previous_month_usage_full_sync", "current_month_usage_full_sync"} { title := Kind(operation) if other, exists := seen[title]; exists { t.Fatalf("%q and %q share title %q", other, operation, title) } seen[title] = operation } } func TestCardTitleNamesTrafficSyncType(t *testing.T) { cases := []struct{ operation, want string }{ {"previous_day_usage_full_sync", "生产 · 日流量同步"}, {"previous_month_usage_full_sync", "生产 · 月历史同步"}, {"current_month_usage_full_sync", "生产 · 本月流量快照同步"}, } for _, c := range cases { a := archive.RunArchive{Version: 1, Run: archive.RunSummary{RunID: "run-title", Operation: c.operation}} body, err := Card(a, "prod") if err != nil { t.Fatal(err) } if !strings.Contains(string(body), `"content":"`+c.want+`"`) { t.Fatalf("card for %q missing title %q: %s", c.operation, c.want, body) } } } func TestTextContainsRoundThreeFailure(t *testing.T) { text := Text(sample(), "preview") for _, want := range []string{"开始时间:2026-09-22 19:42:34", "结束时间:2026-09-22 20:32:01", "实际执行:3 轮", "第 3 轮", "终态失败 9,000", "5分5秒", "0.00%"} { if !strings.Contains(text, want) { t.Fatalf("text missing %q:\n%s", want, text) } } if strings.Contains(text, "2026-09-22 20:26:56") { t.Fatalf("text exposes per-round start time: %s", text) } } func TestCardIsStructuredAndShowsFullRunID(t *testing.T) { body, err := Card(sample(), "preview") if err != nil { t.Fatal(err) } value := string(body) for _, want := range []string{ `"msg_type":"interactive"`, `"content":"预演 · 卡状态全量同步"`, `"fields"`, `**开始时间**\n2026-09-22 19:42:34`, `**结束时间**\n2026-09-22 20:32:01`, `第 3 轮 · 9,000 张 · 5分5秒`, `进入下轮 0 · 终态失败 9,000`, `Run: run-1`, } { if !strings.Contains(value, want) { t.Fatalf("card missing %q: %s", want, body) } } if strings.Contains(value, "2026-09-22 20:26:56") { t.Fatalf("card exposes per-round start time: %s", body) } } func TestCardShowsFullRunID(t *testing.T) { runID := "sim-status-20260922194233-c96b21ec7d3746ae9caef457e89faa41" card, err := Card(archive.RunArchive{Version: 1, Run: archive.RunSummary{RunID: runID}}, "preview") if err != nil { t.Fatal(err) } if !strings.Contains(string(card), "Run: "+runID) { t.Fatalf("card truncated Run ID: %s", card) } }