Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
logmodel "github.com/perfect-panel/server/internal/model/log"
|
||||
usermodel "github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func TestQueryWithdrawalLog_WithWithdrawalBizType(t *testing.T) {
|
||||
const userID = int64(42)
|
||||
createdAt := time.Unix(1700000000, 0)
|
||||
updatedAt := createdAt.Add(time.Minute)
|
||||
|
||||
db, mock, cleanup := newQueryWithdrawalLogTestDB(t)
|
||||
defer cleanup()
|
||||
|
||||
mock.ExpectQuery("SELECT count(*) FROM `withdrawals` WHERE user_id = ?").
|
||||
WithArgs(userID).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
||||
mock.ExpectQuery("SELECT * FROM `withdrawals` WHERE user_id = ? ORDER BY id DESC LIMIT ?").
|
||||
WithArgs(userID, 10).
|
||||
WillReturnRows(sqlmock.NewRows([]string{
|
||||
"id", "user_id", "amount", "content", "status", "reason", "method", "account", "qr_code_url", "created_at", "updated_at",
|
||||
}).AddRow(
|
||||
int64(1001), userID, int64(3000), "bank withdrawal", usermodel.WithdrawalStatusPending, "", uint8(3), "acct-001", "", createdAt, updatedAt,
|
||||
))
|
||||
|
||||
logic := newTestQueryWithdrawalLogLogic(t, db, userID)
|
||||
resp, err := logic.QueryWithdrawalLog(&types.QueryWithdrawalLogListRequest{
|
||||
BizType: withdrawalLogBizTypeWithdrawal,
|
||||
Page: 1,
|
||||
Size: 10,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("QueryWithdrawalLog unexpected error: %v", err)
|
||||
}
|
||||
if resp.Total != 1 || len(resp.List) != 1 {
|
||||
t.Fatalf("QueryWithdrawalLog response = %+v, want one withdrawal", resp)
|
||||
}
|
||||
got := resp.List[0]
|
||||
if got.BizType != withdrawalLogBizTypeWithdrawal {
|
||||
t.Fatalf("BizType = %q, want %q", got.BizType, withdrawalLogBizTypeWithdrawal)
|
||||
}
|
||||
if got.Id != 1001 || got.UserId != userID || got.Amount != 3000 || got.CreatedAt != createdAt.UnixMilli() || got.UpdatedAt != updatedAt.UnixMilli() {
|
||||
t.Fatalf("withdrawal item = %+v", got)
|
||||
}
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Fatalf("unmet sql expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQueryWithdrawalLog_WithCommissionRefundBizType(t *testing.T) {
|
||||
const userID = int64(42)
|
||||
content := `{"type":333,"amount":2500,"order_no":"ORDER-1","timestamp":1700000000123}`
|
||||
createdAt := time.Unix(1700000000, 0)
|
||||
|
||||
db, mock, cleanup := newQueryWithdrawalLogTestDB(t)
|
||||
defer cleanup()
|
||||
|
||||
mock.ExpectQuery("SELECT count(*) FROM `system_logs` WHERE `type` = ? AND object_id = ? AND `content` LIKE ?").
|
||||
WithArgs(logmodel.TypeCommission.Uint8(), userID, "%\"type\":333%").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
||||
mock.ExpectQuery("SELECT * FROM `system_logs` WHERE `type` = ? AND object_id = ? AND `content` LIKE ? ORDER BY id DESC LIMIT ?").
|
||||
WithArgs(logmodel.TypeCommission.Uint8(), userID, "%\"type\":333%", 10).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "type", "date", "object_id", "content", "created_at"}).
|
||||
AddRow(int64(2001), logmodel.TypeCommission.Uint8(), "2023-11-14", userID, content, createdAt))
|
||||
|
||||
logic := newTestQueryWithdrawalLogLogic(t, db, userID)
|
||||
resp, err := logic.QueryWithdrawalLog(&types.QueryWithdrawalLogListRequest{
|
||||
BizType: withdrawalLogBizTypeCommissionRefund,
|
||||
Page: 1,
|
||||
Size: 10,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("QueryWithdrawalLog unexpected error: %v", err)
|
||||
}
|
||||
if resp.Total != 1 || len(resp.List) != 1 {
|
||||
t.Fatalf("QueryWithdrawalLog response = %+v, want one commission refund", resp)
|
||||
}
|
||||
got := resp.List[0]
|
||||
if got.BizType != withdrawalLogBizTypeCommissionRefund {
|
||||
t.Fatalf("BizType = %q, want %q", got.BizType, withdrawalLogBizTypeCommissionRefund)
|
||||
}
|
||||
if got.Id != 2001 || got.UserId != userID || got.Amount != 2500 || got.Content != content || got.CreatedAt != 1700000000123 || got.UpdatedAt != 1700000000123 {
|
||||
t.Fatalf("commission refund item = %+v", got)
|
||||
}
|
||||
if got.Status != 0 || got.Method != 0 || got.Account != "" || got.QrCodeUrl != "" {
|
||||
t.Fatalf("commission refund withdrawal-only fields = %+v, want zero values", got)
|
||||
}
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Fatalf("unmet sql expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQueryWithdrawalLog_RejectsInvalidBizType(t *testing.T) {
|
||||
db, mock, cleanup := newQueryWithdrawalLogTestDB(t)
|
||||
defer cleanup()
|
||||
|
||||
logic := newTestQueryWithdrawalLogLogic(t, db, 42)
|
||||
_, err := logic.QueryWithdrawalLog(&types.QueryWithdrawalLogListRequest{
|
||||
BizType: "all",
|
||||
Page: 1,
|
||||
Size: 10,
|
||||
})
|
||||
if !isQueryWithdrawalLogErrCode(err, xerr.InvalidParams) {
|
||||
t.Fatalf("QueryWithdrawalLog err = %v, want InvalidParams", err)
|
||||
}
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Fatalf("unmet sql expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func newQueryWithdrawalLogTestDB(t *testing.T) (*gorm.DB, sqlmock.Sqlmock, func()) {
|
||||
t.Helper()
|
||||
|
||||
sqlDB, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherFunc(func(expectedSQL, actualSQL string) error {
|
||||
if strings.Contains(actualSQL, expectedSQL) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("actual sql %q does not contain %q", actualSQL, expectedSQL)
|
||||
})))
|
||||
if err != nil {
|
||||
t.Fatalf("create sqlmock: %v", err)
|
||||
}
|
||||
|
||||
db, err := gorm.Open(mysql.New(mysql.Config{Conn: sqlDB, SkipInitializeWithVersion: true}), &gorm.Config{})
|
||||
if err != nil {
|
||||
_ = sqlDB.Close()
|
||||
t.Fatalf("open gorm db: %v", err)
|
||||
}
|
||||
|
||||
return db, mock, func() {
|
||||
_ = sqlDB.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func newTestQueryWithdrawalLogLogic(t *testing.T, db *gorm.DB, userID int64) *QueryWithdrawalLogLogic {
|
||||
t.Helper()
|
||||
ctx := context.WithValue(context.Background(), constant.CtxKeyUser, &usermodel.User{Id: userID})
|
||||
return &QueryWithdrawalLogLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: &svc.ServiceContext{
|
||||
DB: db,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func queryWithdrawalLogErrCodeOf(err error) uint32 {
|
||||
if err == nil {
|
||||
return 0
|
||||
}
|
||||
type coder interface {
|
||||
GetErrCode() uint32
|
||||
}
|
||||
cause := errors.Cause(err)
|
||||
if c, ok := cause.(coder); ok {
|
||||
return c.GetErrCode()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func isQueryWithdrawalLogErrCode(err error, code uint32) bool {
|
||||
return queryWithdrawalLogErrCodeOf(err) == code
|
||||
}
|
||||
Reference in New Issue
Block a user