150 lines
4.6 KiB
Go
150 lines
4.6 KiB
Go
package httpapi
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.118im.com/im_team/im_workbench/internal/store"
|
|
)
|
|
|
|
func TestPayloadUserIDsAreStrings(t *testing.T) {
|
|
now := time.Date(2026, 9, 16, 9, 30, 0, 0, time.UTC)
|
|
userA, err := parseUserID("usrag7w9xJ6hto")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
userB, err := parseUserID("usr1RqTFgHSenM")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
payloads := []map[string]any{
|
|
organizationMemberPayload(store.OrganizationMember{UserID: userA}),
|
|
attendanceRecordPayload(&store.AttendanceRecord{RecordID: "att_1", UserID: userA, Date: now, CreatedAt: now, UpdatedAt: now}),
|
|
attendanceAppealPayload(&store.AttendanceAppeal{AppealID: "atta_1", UserID: userA, SubmittedAt: now, CreatedAt: now, UpdatedAt: now}),
|
|
meetingPayload(store.Meeting{
|
|
MeetingID: "mtg_1",
|
|
OrganizerID: userA,
|
|
RecorderID: userB,
|
|
StartAt: now,
|
|
EndAt: now.Add(time.Hour),
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
Participants: []store.MeetingParticipant{
|
|
{UserID: userA, Response: "accepted"},
|
|
{UserID: userB, Response: "pending"},
|
|
},
|
|
}, userA),
|
|
meetingNoteFilePayload(store.MeetingNoteFile{NoteFileID: "mnote_1", UploaderID: userA, CreatedAt: now, UpdatedAt: now}, userA),
|
|
dailyReportPayload(store.DailyReport{ReportID: "dr_1", AuthorID: userA, ReportDate: now, CreatedAt: now, UpdatedAt: now}),
|
|
monthlyReportPayload(store.MonthlyReport{ReportID: "mr_1", AuthorID: userA, CreatedAt: now, UpdatedAt: now}),
|
|
mailboxSubmissionPayload(store.MailboxSubmission{SubmissionID: "mb_1", SenderID: userA, SubmittedAt: now}),
|
|
}
|
|
|
|
for _, payload := range payloads {
|
|
assertNoNumericUserIDs(t, payload)
|
|
}
|
|
}
|
|
|
|
func TestMeetingPayloadIncludesNamesAndDerivedEndedState(t *testing.T) {
|
|
now := time.Now().UTC()
|
|
userA, err := parseUserID("usrag7w9xJ6hto")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
userB, err := parseUserID("usr1RqTFgHSenM")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
payload := meetingPayload(store.Meeting{
|
|
MeetingID: "mtg_1",
|
|
Title: "周会",
|
|
OrganizerID: userA,
|
|
RecorderID: userA,
|
|
Organizer: store.UserSummary{UserID: userA, DisplayName: "张三"},
|
|
Recorder: store.UserSummary{UserID: userA, DisplayName: "张三"},
|
|
StartAt: now.Add(-2 * time.Hour),
|
|
EndAt: now.Add(-time.Hour),
|
|
State: "scheduled",
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
Participants: []store.MeetingParticipant{
|
|
{UserID: userB, Response: "pending", User: store.UserSummary{UserID: userB, DisplayName: "李四"}},
|
|
},
|
|
}, userA)
|
|
|
|
if payload["state"] != "ended" {
|
|
t.Fatalf("state=%v, want ended", payload["state"])
|
|
}
|
|
if payload["organizer_display_name"] != "张三" {
|
|
t.Fatalf("organizer_display_name=%v", payload["organizer_display_name"])
|
|
}
|
|
names, ok := payload["participant_names"].([]string)
|
|
if !ok || len(names) != 1 || names[0] != "李四" {
|
|
t.Fatalf("participant_names=%#v", payload["participant_names"])
|
|
}
|
|
participants, ok := payload["participants"].([]map[string]any)
|
|
if !ok || len(participants) != 1 || participants[0]["display_name"] != "李四" {
|
|
t.Fatalf("participants=%#v", payload["participants"])
|
|
}
|
|
}
|
|
|
|
func TestMeetingNoteFilePayloadKeepsOriginalNameAndExtension(t *testing.T) {
|
|
now := time.Date(2026, 9, 17, 12, 0, 0, 0, time.UTC)
|
|
payload := meetingNoteFilePayload(store.MeetingNoteFile{
|
|
NoteFileID: "mnote_1",
|
|
FileID: "file_1",
|
|
FileName: "会议纪要.pdf",
|
|
MIMEType: "application/pdf",
|
|
FileSize: 2048,
|
|
UploaderID: 1,
|
|
Status: "active",
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}, 1)
|
|
if payload["file_name"] != "会议纪要.pdf" || payload["name"] != "会议纪要.pdf" {
|
|
t.Fatalf("payload names = file_name:%v name:%v", payload["file_name"], payload["name"])
|
|
}
|
|
if payload["file_extension"] != "pdf" {
|
|
t.Fatalf("file_extension = %v, want pdf", payload["file_extension"])
|
|
}
|
|
if payload["mime"] != "application/pdf" || payload["size"] != int64(2048) {
|
|
t.Fatalf("payload aliases = mime:%v size:%v", payload["mime"], payload["size"])
|
|
}
|
|
}
|
|
|
|
func assertNoNumericUserIDs(t *testing.T, value any) {
|
|
t.Helper()
|
|
switch typed := value.(type) {
|
|
case map[string]any:
|
|
for key, item := range typed {
|
|
if isUserIDKey(key) {
|
|
if _, ok := item.(string); !ok {
|
|
t.Fatalf("%s is %T, want string", key, item)
|
|
}
|
|
}
|
|
assertNoNumericUserIDs(t, item)
|
|
}
|
|
case []map[string]any:
|
|
for _, item := range typed {
|
|
assertNoNumericUserIDs(t, item)
|
|
}
|
|
case []any:
|
|
for _, item := range typed {
|
|
assertNoNumericUserIDs(t, item)
|
|
}
|
|
}
|
|
}
|
|
|
|
func isUserIDKey(key string) bool {
|
|
return key == "user_id" ||
|
|
key == "organizer_id" ||
|
|
key == "recorder_user_id" ||
|
|
key == "uploader_user_id" ||
|
|
key == "author_id" ||
|
|
key == "sender_id" ||
|
|
strings.HasSuffix(key, "_user_id")
|
|
}
|