Files
iotlcm/internal/render/card_test.go
T
MiFaZhan 5732bf3384 chore: 初始开源发布
iotlcm-bot:独立飞书应用机器人(读取 Worker 终态 Run JSON,渲染并发送全量同步结果卡片)。

- Go module:git.5iot.com/iotlcm/iotlcm-bot → git.5iot.com/iotlcm-public/iotlcm-bot
- 飞书凭据占位:appId/appSecret/chatId → ${FEISHU_APP_ID}/${FEISHU_APP_SECRET}/${FEISHU_CHAT_ID}
- 移除内部资产:CI 触发器
- Dockerfile 改用公共基础镜像(golang:1.25-alpine → scratch)
- README 重写(命令/配置/挂载契约/常见问题),去掉内部环境路径
- 补 Apache-2.0 LICENSE,LF 行尾 + .gitattributes
2026-10-22 16:14:24 +08:00

111 lines
4.1 KiB
Go

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)
}
}