Files
olons_server/internal/portal/service_test.go
T

129 lines
4.1 KiB
Go

package portal
import (
"context"
"database/sql"
"encoding/json"
"errors"
"strings"
"testing"
"git.118im.com/im_team/im_workbench/internal/accounts"
"git.118im.com/im_team/im_workbench/internal/store"
)
type fakeRepository struct {
config json.RawMessage
banners []store.Banner
content *store.Content
levels []store.MemberLevel
notices []store.MemberNotice
summary *store.TaskSummary
}
func (r fakeRepository) CurrentSiteConfig(context.Context, int64) (json.RawMessage, error) {
return r.config, nil
}
func (r fakeRepository) ActiveBanners(context.Context, int64, string) ([]store.Banner, error) {
return r.banners, nil
}
func (r fakeRepository) PublishedContent(context.Context, int64, string) (*store.Content, error) {
if r.content == nil {
return nil, store.ErrResourceNotFound
}
return r.content, nil
}
func (r fakeRepository) ActiveMemberLevels(context.Context, int64) ([]store.MemberLevel, error) {
return r.levels, nil
}
func (r fakeRepository) ActiveMemberNotices(context.Context, int64, int64, int) ([]store.MemberNotice, error) {
return r.notices, nil
}
func (r fakeRepository) MemberTaskSummary(context.Context, int64, int64) (*store.TaskSummary, error) {
return r.summary, nil
}
func TestParseFeaturesSupportsNestedAndLegacyKeys(t *testing.T) {
features := parseFeatures(json.RawMessage(`{
"features":{"task_enabled":true,"rechargeEnabled":1},
"WITHDRAWAL":"on","SHOP_STATUS":"false"
}`))
if !features.TaskEnabled || !features.RechargeEnabled || !features.WithdrawalEnabled || features.ManualMallEnabled {
t.Fatalf("unexpected features: %+v", features)
}
}
func TestBannersSanitizeTargets(t *testing.T) {
service := New(fakeRepository{banners: []store.Banner{
{ID: 1, TargetType: 2, TargetValue: "/receive"},
{ID: 2, TargetType: 2, TargetValue: "//evil.example"},
{ID: 3, TargetType: 3, TargetValue: "https://example.com/path"},
{ID: 4, TargetType: 3, TargetValue: "javascript:alert(1)"},
}})
items, err := service.Banners(context.Background(), 0, "home_top")
if err != nil {
t.Fatal(err)
}
wantTypes := []string{"internal_route", "none", "external_url", "none"}
for i, want := range wantTypes {
if items[i].TargetType != want {
t.Errorf("item %d target type = %q, want %q", i, items[i].TargetType, want)
}
}
}
func TestBannersRejectInvalidPosition(t *testing.T) {
service := New(fakeRepository{})
if _, err := service.Banners(context.Background(), 0, "../home"); !errors.Is(err, ErrPositionInvalid) {
t.Fatalf("error = %v, want %v", err, ErrPositionInvalid)
}
}
func TestContentMapsAssets(t *testing.T) {
service := New(fakeRepository{content: &store.Content{
ContentKey: "privacy_policy", Title: "Policy", AssetIDs: sql.NullString{String: `[1,2]`, Valid: true},
}})
content, err := service.Content(context.Background(), 0, "privacy_policy")
if err != nil {
t.Fatal(err)
}
if len(content.AssetIDs) != 2 || content.AssetIDs[0] != 1 || content.AssetIDs[1] != 2 {
t.Fatalf("unexpected asset IDs: %v", content.AssetIDs)
}
}
func TestMemberLevelsAlwaysReturnJSONObjectRules(t *testing.T) {
service := New(fakeRepository{levels: []store.MemberLevel{{ID: 1, Code: "VIP1", Name: "Normal"}}})
levels, err := service.MemberLevels(context.Background(), 0)
if err != nil {
t.Fatal(err)
}
if string(levels[0].Rules) != `{}` {
t.Fatalf("rules = %s, want {}", levels[0].Rules)
}
}
func TestHomeUsesSettledSummaryAndSnakeCaseJSON(t *testing.T) {
service := New(fakeRepository{
config: json.RawMessage(`{"features":{"task_enabled":true}}`),
summary: &store.TaskSummary{TodayCount: 2, TodayCommissionAmount: 150},
})
home, err := service.Home(context.Background(), 0, 7, &accounts.Profile{
Username: "alice", Level: accounts.ProfileLevel{Name: "VIP1"},
Wallet: accounts.ProfileWallet{Currency: "CNY"},
})
if err != nil {
t.Fatal(err)
}
encoded, err := json.Marshal(home)
if err != nil {
t.Fatal(err)
}
text := string(encoded)
for _, field := range []string{`"today_count":2`, `"today_commission_amount":150`, `"task_enabled":true`} {
if !strings.Contains(text, field) {
t.Errorf("home JSON %s does not contain %s", text, field)
}
}
}