package main import ( "testing" "time" ) // TestParseNoticeAddFlags_Valid verifies the happy path parses all fields, // including --expires → 23:59:59 UTC on the given day. func TestParseNoticeAddFlags_Valid(t *testing.T) { in, err := parseNoticeAddFlags([]string{ "-type", "important", "-title-zh", "维护通知", "-title-en", "Maintenance notice", "-body-zh", "今晚维护", "-body-en", "Maintenance tonight", "-link", "https://example.com/notice/1", "-expires", "2026-08-01", "-email", }) if err != nil { t.Fatalf("parseNoticeAddFlags: unexpected error: %v", err) } if in.Type != "important" { t.Errorf("Type = %q, want important", in.Type) } if in.TitleZH != "维护通知" || in.TitleEN != "Maintenance notice" { t.Errorf("titles = %q/%q", in.TitleZH, in.TitleEN) } if !in.Email { t.Errorf("Email = false, want true") } if in.ExpiresAt == nil { t.Fatalf("ExpiresAt is nil, want set") } want := time.Date(2026, 8, 1, 23, 59, 59, 0, time.UTC) if !in.ExpiresAt.Equal(want) { t.Errorf("ExpiresAt = %v, want %v", in.ExpiresAt, want) } } // TestParseNoticeAddFlags_NoExpires verifies omitting --expires leaves it nil. func TestParseNoticeAddFlags_NoExpires(t *testing.T) { in, err := parseNoticeAddFlags([]string{ "-type", "feature", "-title-zh", "新功能", "-title-en", "New feature", }) if err != nil { t.Fatalf("parseNoticeAddFlags: unexpected error: %v", err) } if in.ExpiresAt != nil { t.Errorf("ExpiresAt = %v, want nil", in.ExpiresAt) } } // TestParseNoticeAddFlags_InvalidType is red case 1: -type outside the six // permitted values must fail before any Service/Store call. func TestParseNoticeAddFlags_InvalidType(t *testing.T) { _, err := parseNoticeAddFlags([]string{ "-type", "bogus", "-title-zh", "标题", "-title-en", "Title", }) if err == nil { t.Fatal("parseNoticeAddFlags: expected error for invalid -type, got nil") } } // TestParseNoticeAddFlags_MissingTitle is red case 2: missing -title-zh or // -title-en must fail. func TestParseNoticeAddFlags_MissingTitle(t *testing.T) { cases := []struct { name string args []string }{ { name: "missing title-zh", args: []string{"-type", "important", "-title-en", "Title"}, }, { name: "missing title-en", args: []string{"-type", "important", "-title-zh", "标题"}, }, { name: "missing both", args: []string{"-type", "important"}, }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { _, err := parseNoticeAddFlags(tc.args) if err == nil { t.Fatalf("parseNoticeAddFlags(%v): expected error for missing title, got nil", tc.args) } }) } } // TestParseNoticeAddFlags_EmailNonImportant is red case 3: -email is only // allowed when -type=important. func TestParseNoticeAddFlags_EmailNonImportant(t *testing.T) { _, err := parseNoticeAddFlags([]string{ "-type", "feature", "-title-zh", "标题", "-title-en", "Title", "-email", }) if err == nil { t.Fatal("parseNoticeAddFlags: expected error for -email on non-important type, got nil") } } // TestParseNoticeAddFlags_BadExpiresFormat is red case 4: -expires must be // YYYY-MM-DD; other formats (slashes, timestamps, garbage) must fail. func TestParseNoticeAddFlags_BadExpiresFormat(t *testing.T) { cases := []string{ "2026/08/01", "08-01-2026", "2026-08-01T00:00:00Z", "not-a-date", } for _, expires := range cases { t.Run(expires, func(t *testing.T) { _, err := parseNoticeAddFlags([]string{ "-type", "important", "-title-zh", "标题", "-title-en", "Title", "-expires", expires, }) if err == nil { t.Fatalf("parseNoticeAddFlags(-expires=%q): expected error, got nil", expires) } }) } }