Files
jiang13-bbs/backend/service/comment_node_test.go

126 lines
3.4 KiB
Go

package service
import (
"encoding/json"
"strings"
"testing"
"time"
"github.com/freefire/jiang13-bbs/model"
"gorm.io/gorm"
)
func staffDeletedComment() model.Comment {
uid := uint(7)
c := model.Comment{
ID: 11,
PostID: 22,
UserID: uid,
Content: "不该出现在公开 JSON",
Status: model.ContentStatusPublished,
DeletedBy: 9,
User: model.User{
ID: uid,
Username: "alice",
Nickname: "爱丽丝",
Avatar: "/uploads/avatars/alice.jpg",
},
}
c.DeletedAt = gorm.DeletedAt{Time: time.Now(), Valid: true}
c.CreatedAt = time.Now().Add(-time.Hour)
c.UpdatedAt = c.CreatedAt
return c
}
func marshalNode(t *testing.T, n CommentNode) map[string]any {
t.Helper()
b, err := json.Marshal(n)
if err != nil {
t.Fatalf("marshal: %v", err)
}
var raw map[string]any
if err := json.Unmarshal(b, &raw); err != nil {
t.Fatalf("unmarshal: %v", err)
}
return raw
}
func TestToCommentNodeHidesStaffDeletedAuthorFromPublic(t *testing.T) {
c := staffDeletedComment()
raw := marshalNode(t, toCommentNode(c, nil, false, 0, nil))
if _, ok := raw["user"]; ok {
t.Fatalf("公众 JSON 不应含 user: %v", raw["user"])
}
if _, ok := raw["user_id"]; ok {
t.Fatalf("公众 JSON 不应含 user_id: %v", raw["user_id"])
}
if raw["staff_deleted"] != true {
t.Fatalf("staff_deleted=%v", raw["staff_deleted"])
}
if s, _ := raw["content"].(string); s != "" {
t.Fatalf("公众不应看到正文: %q", s)
}
blob, _ := json.Marshal(raw)
for _, leak := range []string{"alice", "爱丽丝", "/uploads/avatars/alice.jpg"} {
if strings.Contains(string(blob), leak) {
t.Fatalf("公众 JSON 泄漏身份 %q: %s", leak, blob)
}
}
}
func TestToCommentNodeKeepsAuthorForCommenter(t *testing.T) {
c := staffDeletedComment()
raw := marshalNode(t, toCommentNode(c, nil, false, 7, nil))
if raw["user_id"] != float64(7) {
t.Fatalf("评论者应看到 user_id: %v", raw["user_id"])
}
user, ok := raw["user"].(map[string]any)
if !ok {
t.Fatalf("评论者应看到 user")
}
if user["username"] != "alice" {
t.Fatalf("username=%v", user["username"])
}
if raw["content"] != "不该出现在公开 JSON" {
t.Fatalf("评论者应看到原文, got %v", raw["content"])
}
}
func TestToCommentNodeKeepsAuthorForModerator(t *testing.T) {
c := staffDeletedComment()
raw := marshalNode(t, toCommentNode(c, nil, true, 99, nil))
if raw["user_id"] != float64(7) {
t.Fatalf("版主应看到 user_id")
}
if _, ok := raw["user"]; !ok {
t.Fatal("版主应看到 user")
}
if raw["content"] != "不该出现在公开 JSON" {
t.Fatalf("版主应看到原文, got %v", raw["content"])
}
}
func TestToCommentNodeSelfDeleteKeepsAuthor(t *testing.T) {
c := staffDeletedComment()
c.DeletedBy = c.UserID
raw := marshalNode(t, toCommentNode(c, nil, false, 0, nil))
if raw["staff_deleted"] != nil && raw["staff_deleted"] != false {
t.Fatalf("自删不应标 staff_deleted: %v", raw["staff_deleted"])
}
if raw["user_id"] != float64(7) {
t.Fatalf("自删应保留作者: %v", raw["user_id"])
}
if s, _ := raw["content"].(string); s != "" {
t.Fatalf("公众不应看到自删正文: %q", s)
}
}
func TestToCommentNodeSelfDeleteKeepsContentForCommenter(t *testing.T) {
c := staffDeletedComment()
c.DeletedBy = c.UserID
raw := marshalNode(t, toCommentNode(c, nil, false, 7, nil))
if raw["content"] != "不该出现在公开 JSON" {
t.Fatalf("自删评论者应看到原文, got %v", raw["content"])
}
}