Open member free-lane for chat initiation; auto-claim on author view; harden lease persist/ownership with readable DOC_BUSY; add notification inbox and supplement-impact HTTP decision APIs wired to composition root.
56 lines
1.3 KiB
Go
56 lines
1.3 KiB
Go
package server
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"chat-agent-system/internal/notification"
|
|
)
|
|
|
|
func TestInboxSeverityRank(t *testing.T) {
|
|
if inboxSeverityRank("proposal_required") != 0 {
|
|
t.Fatalf("proposal_required should rank first")
|
|
}
|
|
if inboxSeverityRank("stage_ready_to_advance") != 1 {
|
|
t.Fatalf("stage ready should be info rank")
|
|
}
|
|
}
|
|
|
|
func TestUserNotificationViewFromCopiesCoreFields(t *testing.T) {
|
|
n := notification.Notification{
|
|
ID: 9, UserID: 2, ProjectID: 3, Type: "stage_ready_to_advance",
|
|
Title: "t", Body: "b", Status: "unread", CreatedAt: time.Unix(1, 0).UTC(),
|
|
}
|
|
v := userNotificationViewFrom(n)
|
|
if v.ID != 9 || v.ProjectID != 3 || v.Title != "t" {
|
|
t.Fatalf("unexpected view: %+v", v)
|
|
}
|
|
}
|
|
|
|
func TestFanOutSortPrefersActionTypes(t *testing.T) {
|
|
raw := []notification.Notification{
|
|
{ID: 1, Type: "stage_ready_to_advance"},
|
|
{ID: 2, Type: "proposal_required"},
|
|
{ID: 3, Type: "stage_ready_to_advance"},
|
|
}
|
|
// mimic fanOut sort
|
|
si := func(i, j int) bool {
|
|
a, b := inboxSeverityRank(raw[i].Type), inboxSeverityRank(raw[j].Type)
|
|
if a != b {
|
|
return a < b
|
|
}
|
|
return raw[i].ID > raw[j].ID
|
|
}
|
|
// bubble
|
|
for i := 0; i < len(raw); i++ {
|
|
for j := i + 1; j < len(raw); j++ {
|
|
if si(j, i) {
|
|
raw[i], raw[j] = raw[j], raw[i]
|
|
}
|
|
}
|
|
}
|
|
if raw[0].Type != "proposal_required" {
|
|
t.Fatalf("expected proposal first, got %+v", raw)
|
|
}
|
|
}
|