Files
quyun-v2/backend/app/services/creator_test.go
Rogee 5cf2295f91 feat: Implement notification service and integrate with user interactions
- Added notification service to handle sending and listing notifications.
- Integrated notification sending on user follow and order payment events.
- Updated user service to include fetching followed tenants.
- Enhanced content service to manage access control for content assets.
- Implemented logic for listing content topics based on genre.
- Updated creator service to manage content updates and pricing.
- Improved order service to include detailed order information and notifications.
- Added tests for notification CRUD operations and order details.
2025-12-30 09:57:12 +08:00

180 lines
6.1 KiB
Go

package services
import (
"context"
"database/sql"
"testing"
"quyun/v2/app/commands/testx"
creator_dto "quyun/v2/app/http/v1/dto"
"quyun/v2/database"
"quyun/v2/database/models"
"quyun/v2/pkg/consts"
. "github.com/smartystreets/goconvey/convey"
"github.com/spf13/cast"
"github.com/stretchr/testify/suite"
"go.ipao.vip/atom/contracts"
"go.uber.org/dig"
)
type CreatorTestSuiteInjectParams struct {
dig.In
DB *sql.DB
Initials []contracts.Initial `group:"initials"`
}
type CreatorTestSuite struct {
suite.Suite
CreatorTestSuiteInjectParams
}
func Test_Creator(t *testing.T) {
providers := testx.Default().With(Provide)
testx.Serve(providers, t, func(p CreatorTestSuiteInjectParams) {
suite.Run(t, &CreatorTestSuite{CreatorTestSuiteInjectParams: p})
})
}
func (s *CreatorTestSuite) Test_Apply() {
Convey("Apply", s.T(), func() {
ctx := s.T().Context()
database.Truncate(ctx, s.DB, models.TableNameTenant, models.TableNameTenantUser, models.TableNameUser)
u := &models.User{Username: "creator1", Phone: "13700000001"}
models.UserQuery.WithContext(ctx).Create(u)
ctx = context.WithValue(ctx, consts.CtxKeyUser, u.ID)
Convey("should create tenant", func() {
form := &creator_dto.ApplyForm{
Name: "My Channel",
}
err := Creator.Apply(ctx, form)
So(err, ShouldBeNil)
t, _ := models.TenantQuery.WithContext(ctx).Where(models.TenantQuery.UserID.Eq(u.ID)).First()
So(t, ShouldNotBeNil)
So(t.Name, ShouldEqual, "My Channel")
So(t.Status, ShouldEqual, consts.TenantStatusPendingVerify)
// Check admin role
tu, _ := models.TenantUserQuery.WithContext(ctx).Where(models.TenantUserQuery.TenantID.Eq(t.ID)).First()
So(tu, ShouldNotBeNil)
// Role is array, check contains? Or first element?
// types.Array is likely []T.
So(len(tu.Role), ShouldEqual, 1)
So(tu.Role[0], ShouldEqual, consts.TenantUserRoleTenantAdmin)
})
})
}
func (s *CreatorTestSuite) Test_CreateContent() {
Convey("CreateContent", s.T(), func() {
ctx := s.T().Context()
database.Truncate(ctx, s.DB, models.TableNameTenant, models.TableNameContent, models.TableNameContentAsset, models.TableNameContentPrice, models.TableNameUser)
u := &models.User{Username: "creator2", Phone: "13700000002"}
models.UserQuery.WithContext(ctx).Create(u)
ctx = context.WithValue(ctx, consts.CtxKeyUser, u.ID)
// Create Tenant manually
t := &models.Tenant{UserID: u.ID, Name: "Channel 2", Code: "123", Status: consts.TenantStatusVerified}
models.TenantQuery.WithContext(ctx).Create(t)
Convey("should create content and assets", func() {
form := &creator_dto.ContentCreateForm{
Title: "New Song",
Genre: "audio",
Price: 9.99,
// MediaIDs: ... need media asset
}
err := Creator.CreateContent(ctx, form)
So(err, ShouldBeNil)
c, _ := models.ContentQuery.WithContext(ctx).Where(models.ContentQuery.Title.Eq("New Song")).First()
So(c, ShouldNotBeNil)
So(c.UserID, ShouldEqual, u.ID)
So(c.TenantID, ShouldEqual, t.ID)
// Check Price
p, _ := models.ContentPriceQuery.WithContext(ctx).Where(models.ContentPriceQuery.ContentID.Eq(c.ID)).First()
So(p, ShouldNotBeNil)
So(p.PriceAmount, ShouldEqual, 999)
})
})
}
func (s *CreatorTestSuite) Test_UpdateContent() {
Convey("UpdateContent", s.T(), func() {
ctx := s.T().Context()
database.Truncate(ctx, s.DB, models.TableNameTenant, models.TableNameContent, models.TableNameContentAsset, models.TableNameContentPrice, models.TableNameUser)
u := &models.User{Username: "creator3", Phone: "13700000003"}
models.UserQuery.WithContext(ctx).Create(u)
ctx = context.WithValue(ctx, consts.CtxKeyUser, u.ID)
t := &models.Tenant{UserID: u.ID, Name: "Channel 3", Code: "124", Status: consts.TenantStatusVerified}
models.TenantQuery.WithContext(ctx).Create(t)
c := &models.Content{TenantID: t.ID, UserID: u.ID, Title: "Old Title", Genre: "audio"}
models.ContentQuery.WithContext(ctx).Create(c)
models.ContentPriceQuery.WithContext(ctx).Create(&models.ContentPrice{TenantID: t.ID, UserID: u.ID, ContentID: c.ID, PriceAmount: 100})
Convey("should update content", func() {
form := &creator_dto.ContentUpdateForm{
Title: "New Title",
Genre: "video",
Price: 20.00,
}
err := Creator.UpdateContent(ctx, cast.ToString(c.ID), form)
So(err, ShouldBeNil)
// Verify
cReload, _ := models.ContentQuery.WithContext(ctx).Where(models.ContentQuery.ID.Eq(c.ID)).First()
So(cReload.Title, ShouldEqual, "New Title")
So(cReload.Genre, ShouldEqual, "video")
p, _ := models.ContentPriceQuery.WithContext(ctx).Where(models.ContentPriceQuery.ContentID.Eq(c.ID)).First()
So(p.PriceAmount, ShouldEqual, 2000)
})
})
}
func (s *CreatorTestSuite) Test_Dashboard() {
Convey("Dashboard", s.T(), func() {
ctx := s.T().Context()
database.Truncate(ctx, s.DB, models.TableNameTenant, models.TableNameTenantUser, models.TableNameTenantLedger, models.TableNameUser, models.TableNameOrder)
u := &models.User{Username: "creator4", Phone: "13700000004"}
models.UserQuery.WithContext(ctx).Create(u)
ctx = context.WithValue(ctx, consts.CtxKeyUser, u.ID)
t := &models.Tenant{UserID: u.ID, Name: "Channel 4", Code: "125", Status: consts.TenantStatusVerified}
models.TenantQuery.WithContext(ctx).Create(t)
// Mock Data
// 1. Followers
models.TenantUserQuery.WithContext(ctx).Create(
&models.TenantUser{TenantID: t.ID, UserID: 100},
&models.TenantUser{TenantID: t.ID, UserID: 101},
)
// 2. Revenue (Ledgers)
models.TenantLedgerQuery.WithContext(ctx).Create(
&models.TenantLedger{TenantID: t.ID, Type: consts.TenantLedgerTypeDebitPurchase, Amount: 1000}, // 10.00
&models.TenantLedger{TenantID: t.ID, Type: consts.TenantLedgerTypeDebitPurchase, Amount: 2000}, // 20.00
&models.TenantLedger{TenantID: t.ID, Type: consts.TenantLedgerTypeCreditRefund, Amount: 500}, // -5.00 (Refund, currently Dashboard sums DebitPurchase only, ideally should subtract refunds, but let's stick to implementation)
)
Convey("should get stats", func() {
stats, err := Creator.Dashboard(ctx)
So(err, ShouldBeNil)
So(stats.TotalFollowers.Value, ShouldEqual, 2)
// Implementation sums 'debit_purchase' only based on my code
So(stats.TotalRevenue.Value, ShouldEqual, 30.00)
})
})
}