Files
OwnCord/Server/api/dm_handler_presence_test.go
T

71 lines
2.5 KiB
Go
Raw Normal View History

package api_test
import (
"context"
"encoding/json"
"net/http"
"testing"
"github.com/J3vb/OwnCord/Server/api"
"github.com/J3vb/OwnCord/Server/auth"
"github.com/J3vb/OwnCord/Server/db"
"github.com/J3vb/OwnCord/Server/service"
"github.com/go-chi/chi/v5"
)
// OC-0304: POST /dms must apply the same "no live connection is offline,
// whatever users.status stores" rule ws/serve_ready.go's
// presentableMembers/presentableDMChannels apply to the ready payload and
// members list. MarkUserDisconnected deliberately keeps a chosen idle/dnd
// status across a disconnect (so a reconnect can honour it), so a
// signed-out recipient's saved "dnd" must not leak into the DM sidebar as a
// live presence dot — contradicting the member list right next to it, which
// would correctly show the same user offline.
func TestCreateDM_RecipientStatus_OfflineWhenDisconnected(t *testing.T) {
database := newDMTestDB(t)
broadcaster := &mockBroadcaster{}
r := chi.NewRouter()
svc := service.New(database, auth.NewRateLimiter())
api.MountDMRoutes(r, database, svc, broadcaster)
tokenAlice := dmCreateToken(t, database, "presence_alice", 4)
_ = dmCreateToken(t, database, "presence_bob", 4)
bob, err := database.GetUserByUsername(context.Background(), "presence_bob")
if err != nil || bob == nil {
t.Fatalf("lookup bob: %v", err)
}
// Bob chose "Do Not Disturb" and then signed out: MarkUserDisconnected
// only ever rewrites the "online" status, so the saved row keeps "dnd".
if _, err := database.ExecContext(context.Background(),
`UPDATE users SET status = 'dnd' WHERE id = ?`, bob.ID,
); err != nil {
t.Fatalf("set bob status: %v", err)
}
// Nobody currently holds a live connection — mirrors a hub with bob's
// session gone.
svc.DMs.SetOnlineChecker(func(userID int64) bool { return false })
rr := dmPost(t, r, "/api/v1/dms", tokenAlice, map[string]any{
"recipient_id": bob.ID,
})
if rr.Code != http.StatusCreated {
t.Fatalf("CreateDM: status = %d, want 201; body = %s", rr.Code, rr.Body.String())
}
var resp map[string]any
if err := json.NewDecoder(rr.Body).Decode(&resp); err != nil {
t.Fatalf("decode response: %v", err)
}
recipient, ok := resp["recipient"].(map[string]any)
if !ok {
t.Fatalf("recipient missing from response: %v", resp)
}
if got := recipient["status"]; got != db.StatusOffline {
t.Errorf("recipient.status = %v, want %q (bob has no live connection, so his saved 'dnd' must not leak into the DM sidebar)",
got, db.StatusOffline)
}
}