package srv_contentexcel import ( "bytes" "math/rand" "testing" "time" "videoweb/pub/models/videoinformationmod" "videoweb/pub/pubdef" "go.mongodb.org/mongo-driver/bson" "github.com/xuri/excelize/v2" ) func TestBuildTimeRangeFilter(t *testing.T) { t.Parallel() filter, err := buildTimeRangeFilter("2026-01-01", "2026-01-31") if err != nil { t.Fatalf("buildTimeRangeFilter() err = %v", err) } if filter["$gte"] == nil || filter["$lte"] == nil { t.Fatalf("buildTimeRangeFilter() = %#v, want range filter", filter) } empty, err := buildTimeRangeFilter("", "") if err != nil { t.Fatalf("buildTimeRangeFilter() empty err = %v", err) } if len(empty) != 0 { t.Fatalf("buildTimeRangeFilter() empty = %#v, want nil/empty", empty) } } func TestApplyStatusFilter(t *testing.T) { t.Parallel() base := bson.M{"a": 1} if got := applyStatusFilter(base, "status", nil); len(got) != 1 { t.Fatalf("nil status should not add filter: %#v", got) } status := pubdef.InformationStatusVerifyOK got := applyStatusFilter(bson.M{}, videoinformationmod.FN.VideoInformation.Status, &status) if got[videoinformationmod.FN.VideoInformation.Status] != pubdef.InformationStatusVerifyOK { t.Fatalf("applyStatusFilter() status = %#v", got[videoinformationmod.FN.VideoInformation.Status]) } start := time.Date(2026, 1, 1, 0, 0, 0, 0, time.Local) end := time.Date(2026, 1, 31, 23, 59, 59, 0, time.Local) dateFilter := bson.M{"$gte": start, "$lte": end} videoFilter := applyIDsFilter(applyStatusFilter( applyTimeFilter(bson.M{}, videoinformationmod.FN.VideoInformation.CreatedAt, dateFilter), videoinformationmod.FN.VideoInformation.Status, &status, ), videoinformationmod.FN.VideoInformation.Id, []int64{1001, 1002}) if videoFilter[videoinformationmod.FN.VideoInformation.CreatedAt] == nil { t.Fatal("expected createdAt filter") } if videoFilter[videoinformationmod.FN.VideoInformation.Status] != pubdef.InformationStatusVerifyOK { t.Fatal("expected status filter") } if videoFilter[videoinformationmod.FN.VideoInformation.Id] == nil { t.Fatal("expected id filter") } } func TestParseExportIDs(t *testing.T) { t.Parallel() ids, err := ParseExportIDs([]string{"1001,1002", "1003"}) if err != nil { t.Fatalf("ParseExportIDs() err = %v", err) } if len(ids) != 3 || ids[0] != 1001 || ids[1] != 1002 || ids[2] != 1003 { t.Fatalf("ParseExportIDs() = %v", ids) } dup, err := ParseExportIDs([]string{"1001", "1001,1002"}) if err != nil { t.Fatalf("ParseExportIDs() dup err = %v", err) } if len(dup) != 2 { t.Fatalf("ParseExportIDs() dup = %v, want 2 unique ids", dup) } if _, err := ParseExportIDs([]string{"abc"}); err == nil { t.Fatal("ParseExportIDs() invalid id should fail") } } func TestParseKeywords(t *testing.T) { t.Parallel() got := parseKeywords("a,b, c;d") want := []string{"a", "b", "c", "d"} if len(got) != len(want) { t.Fatalf("parseKeywords() = %v, want %v", got, want) } for i := range want { if got[i] != want[i] { t.Fatalf("parseKeywords()[%d] = %q, want %q", i, got[i], want[i]) } } } func TestMapHeaderColumns(t *testing.T) { t.Parallel() index := mapHeaderColumns([]string{"ID", "标题", "描述", "关键词"}) for i := 0; i < excelHeaders; i++ { if _, ok := index[i]; !ok { t.Fatalf("missing column index %d", i) } } } func TestParseWorkbook(t *testing.T) { t.Parallel() rows := []ContentRow{{ ID: 1001, Title: "标题A", Desc: "描述A", Keyworld: []string{"k1", "k2"}, }} data, err := buildWorkbook(rows) if err != nil { t.Fatalf("buildWorkbook() err = %v", err) } parsed, err := parseWorkbook(data) if err != nil { t.Fatalf("parseWorkbook() err = %v", err) } if len(parsed) != 1 { t.Fatalf("parseWorkbook() len = %d, want 1", len(parsed)) } if parsed[0].ID != 1001 || parsed[0].Title != "标题A" { t.Fatalf("parseWorkbook() = %+v", parsed[0]) } } func TestParseWorkbookSkipRedLineRemark(t *testing.T) { t.Parallel() f := excelize.NewFile() defer f.Close() if err := f.SetSheetRow(sheetName, "A1", &[]string{colID, colTitle, colDesc, colKeyworld, colRedLineRemark}); err != nil { t.Fatalf("SetSheetRow header err = %v", err) } if err := f.SetSheetRow(sheetName, "A2", &[]any{1001, "标题A", "描述A", "k1", "建议下架"}); err != nil { t.Fatalf("SetSheetRow row1 err = %v", err) } if err := f.SetSheetRow(sheetName, "A3", &[]any{1002, "标题B", "描述B", "k2", ""}); err != nil { t.Fatalf("SetSheetRow row2 err = %v", err) } var buf bytes.Buffer if err := f.Write(&buf); err != nil { t.Fatalf("Write() err = %v", err) } parsed, err := parseWorkbook(buf.Bytes()) if err != nil { t.Fatalf("parseWorkbook() err = %v", err) } if len(parsed) != 1 { t.Fatalf("parseWorkbook() len = %d, want 1", len(parsed)) } if parsed[0].ID != 1002 { t.Fatalf("parseWorkbook() ID = %d, want 1002", parsed[0].ID) } } func TestRandomImportAddedTime(t *testing.T) { t.Parallel() r := rand.New(rand.NewSource(1)) for i := 0; i < 20; i++ { got := randomImportAddedTime(r) if got.Before(importAddedTimeStart) { t.Fatalf("randomImportAddedTime() = %v, before %v", got, importAddedTimeStart) } if got.After(time.Now()) { t.Fatalf("randomImportAddedTime() = %v, after now", got) } } } func TestNormalizeContentType(t *testing.T) { t.Parallel() if _, err := normalizeContentType("video"); err != nil { t.Fatalf("video should be valid: %v", err) } if _, err := normalizeContentType("post"); err == nil { t.Fatal("post should be invalid") } }