admin_service_search_test.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. //go:build unit
  2. package service
  3. import (
  4. "context"
  5. "testing"
  6. "github.com/Wei-Shaw/sub2api/internal/pkg/pagination"
  7. "github.com/stretchr/testify/require"
  8. )
  9. type accountRepoStubForAdminList struct {
  10. accountRepoStub
  11. listWithFiltersCalls int
  12. listWithFiltersParams pagination.PaginationParams
  13. listWithFiltersPlatform string
  14. listWithFiltersType string
  15. listWithFiltersStatus string
  16. listWithFiltersSearch string
  17. listWithFiltersPrivacy string
  18. listWithFiltersAccounts []Account
  19. listWithFiltersResult *pagination.PaginationResult
  20. listWithFiltersErr error
  21. }
  22. func (s *accountRepoStubForAdminList) ListAllWithFilters(context.Context, string, string, string, string, int64, string) ([]Account, error) {
  23. return nil, nil
  24. }
  25. func (s *accountRepoStubForAdminList) ListWithFilters(_ context.Context, params pagination.PaginationParams, platform, accountType, status, search string, groupID int64, privacyMode string) ([]Account, *pagination.PaginationResult, error) {
  26. s.listWithFiltersCalls++
  27. s.listWithFiltersParams = params
  28. s.listWithFiltersPlatform = platform
  29. s.listWithFiltersType = accountType
  30. s.listWithFiltersStatus = status
  31. s.listWithFiltersSearch = search
  32. s.listWithFiltersPrivacy = privacyMode
  33. if s.listWithFiltersErr != nil {
  34. return nil, nil, s.listWithFiltersErr
  35. }
  36. result := s.listWithFiltersResult
  37. if result == nil {
  38. result = &pagination.PaginationResult{
  39. Total: int64(len(s.listWithFiltersAccounts)),
  40. Page: params.Page,
  41. PageSize: params.PageSize,
  42. }
  43. }
  44. return s.listWithFiltersAccounts, result, nil
  45. }
  46. type proxyRepoStubForAdminList struct {
  47. proxyRepoStub
  48. listWithFiltersCalls int
  49. listWithFiltersParams pagination.PaginationParams
  50. listWithFiltersProtocol string
  51. listWithFiltersStatus string
  52. listWithFiltersSearch string
  53. listWithFiltersProxies []Proxy
  54. listWithFiltersResult *pagination.PaginationResult
  55. listWithFiltersErr error
  56. listWithFiltersAndAccountCountCalls int
  57. listWithFiltersAndAccountCountParams pagination.PaginationParams
  58. listWithFiltersAndAccountCountProtocol string
  59. listWithFiltersAndAccountCountStatus string
  60. listWithFiltersAndAccountCountSearch string
  61. listWithFiltersAndAccountCountProxies []ProxyWithAccountCount
  62. listWithFiltersAndAccountCountResult *pagination.PaginationResult
  63. listWithFiltersAndAccountCountErr error
  64. }
  65. func (s *proxyRepoStubForAdminList) ListWithFilters(_ context.Context, params pagination.PaginationParams, protocol, status, search string) ([]Proxy, *pagination.PaginationResult, error) {
  66. s.listWithFiltersCalls++
  67. s.listWithFiltersParams = params
  68. s.listWithFiltersProtocol = protocol
  69. s.listWithFiltersStatus = status
  70. s.listWithFiltersSearch = search
  71. if s.listWithFiltersErr != nil {
  72. return nil, nil, s.listWithFiltersErr
  73. }
  74. result := s.listWithFiltersResult
  75. if result == nil {
  76. result = &pagination.PaginationResult{
  77. Total: int64(len(s.listWithFiltersProxies)),
  78. Page: params.Page,
  79. PageSize: params.PageSize,
  80. }
  81. }
  82. return s.listWithFiltersProxies, result, nil
  83. }
  84. func (s *proxyRepoStubForAdminList) ListWithFiltersAndAccountCount(_ context.Context, params pagination.PaginationParams, protocol, status, search string) ([]ProxyWithAccountCount, *pagination.PaginationResult, error) {
  85. s.listWithFiltersAndAccountCountCalls++
  86. s.listWithFiltersAndAccountCountParams = params
  87. s.listWithFiltersAndAccountCountProtocol = protocol
  88. s.listWithFiltersAndAccountCountStatus = status
  89. s.listWithFiltersAndAccountCountSearch = search
  90. if s.listWithFiltersAndAccountCountErr != nil {
  91. return nil, nil, s.listWithFiltersAndAccountCountErr
  92. }
  93. result := s.listWithFiltersAndAccountCountResult
  94. if result == nil {
  95. result = &pagination.PaginationResult{
  96. Total: int64(len(s.listWithFiltersAndAccountCountProxies)),
  97. Page: params.Page,
  98. PageSize: params.PageSize,
  99. }
  100. }
  101. return s.listWithFiltersAndAccountCountProxies, result, nil
  102. }
  103. type redeemRepoStubForAdminList struct {
  104. redeemRepoStub
  105. listWithFiltersCalls int
  106. listWithFiltersParams pagination.PaginationParams
  107. listWithFiltersType string
  108. listWithFiltersStatus string
  109. listWithFiltersSearch string
  110. listWithFiltersCodes []RedeemCode
  111. listWithFiltersResult *pagination.PaginationResult
  112. listWithFiltersErr error
  113. }
  114. func (s *redeemRepoStubForAdminList) ListWithFilters(_ context.Context, params pagination.PaginationParams, codeType, status, search string) ([]RedeemCode, *pagination.PaginationResult, error) {
  115. s.listWithFiltersCalls++
  116. s.listWithFiltersParams = params
  117. s.listWithFiltersType = codeType
  118. s.listWithFiltersStatus = status
  119. s.listWithFiltersSearch = search
  120. if s.listWithFiltersErr != nil {
  121. return nil, nil, s.listWithFiltersErr
  122. }
  123. result := s.listWithFiltersResult
  124. if result == nil {
  125. result = &pagination.PaginationResult{
  126. Total: int64(len(s.listWithFiltersCodes)),
  127. Page: params.Page,
  128. PageSize: params.PageSize,
  129. }
  130. }
  131. return s.listWithFiltersCodes, result, nil
  132. }
  133. func (s *redeemRepoStubForAdminList) ListByUserPaginated(_ context.Context, userID int64, params pagination.PaginationParams, codeType string) ([]RedeemCode, *pagination.PaginationResult, error) {
  134. panic("unexpected ListByUserPaginated call")
  135. }
  136. func (s *redeemRepoStubForAdminList) SumPositiveBalanceByUser(_ context.Context, userID int64) (float64, error) {
  137. panic("unexpected SumPositiveBalanceByUser call")
  138. }
  139. func TestAdminService_ListAccounts_WithSearch(t *testing.T) {
  140. t.Run("search 参数正常传递到 repository 层", func(t *testing.T) {
  141. repo := &accountRepoStubForAdminList{
  142. listWithFiltersAccounts: []Account{{ID: 1, Name: "acc"}},
  143. listWithFiltersResult: &pagination.PaginationResult{Total: 10},
  144. }
  145. svc := &adminServiceImpl{accountRepo: repo}
  146. accounts, total, err := svc.ListAccounts(context.Background(), 1, 20, PlatformGemini, AccountTypeOAuth, StatusActive, "acc", 0, "", "name", "ASC")
  147. require.NoError(t, err)
  148. require.Equal(t, int64(10), total)
  149. require.Equal(t, []Account{{ID: 1, Name: "acc"}}, accounts)
  150. require.Equal(t, 1, repo.listWithFiltersCalls)
  151. require.Equal(t, pagination.PaginationParams{Page: 1, PageSize: 20, SortBy: "name", SortOrder: "ASC"}, repo.listWithFiltersParams)
  152. require.Equal(t, PlatformGemini, repo.listWithFiltersPlatform)
  153. require.Equal(t, AccountTypeOAuth, repo.listWithFiltersType)
  154. require.Equal(t, StatusActive, repo.listWithFiltersStatus)
  155. require.Equal(t, "acc", repo.listWithFiltersSearch)
  156. })
  157. }
  158. func TestAdminService_ListAccounts_WithPrivacyMode(t *testing.T) {
  159. t.Run("privacy_mode 参数正常传递到 repository 层", func(t *testing.T) {
  160. repo := &accountRepoStubForAdminList{
  161. listWithFiltersAccounts: []Account{{ID: 2, Name: "acc2"}},
  162. listWithFiltersResult: &pagination.PaginationResult{Total: 1},
  163. }
  164. svc := &adminServiceImpl{accountRepo: repo}
  165. accounts, total, err := svc.ListAccounts(context.Background(), 1, 20, PlatformOpenAI, AccountTypeOAuth, StatusActive, "acc2", 0, PrivacyModeCFBlocked, "", "")
  166. require.NoError(t, err)
  167. require.Equal(t, int64(1), total)
  168. require.Equal(t, []Account{{ID: 2, Name: "acc2"}}, accounts)
  169. require.Equal(t, PrivacyModeCFBlocked, repo.listWithFiltersPrivacy)
  170. })
  171. }
  172. func TestAdminService_ListProxies_WithSearch(t *testing.T) {
  173. t.Run("search 参数正常传递到 repository 层", func(t *testing.T) {
  174. repo := &proxyRepoStubForAdminList{
  175. listWithFiltersProxies: []Proxy{{ID: 2, Name: "p1"}},
  176. listWithFiltersResult: &pagination.PaginationResult{Total: 7},
  177. }
  178. svc := &adminServiceImpl{proxyRepo: repo}
  179. proxies, total, err := svc.ListProxies(context.Background(), 3, 50, "http", StatusActive, "p1", "name", "ASC")
  180. require.NoError(t, err)
  181. require.Equal(t, int64(7), total)
  182. require.Equal(t, []Proxy{{ID: 2, Name: "p1"}}, proxies)
  183. require.Equal(t, 1, repo.listWithFiltersCalls)
  184. require.Equal(t, pagination.PaginationParams{Page: 3, PageSize: 50, SortBy: "name", SortOrder: "ASC"}, repo.listWithFiltersParams)
  185. require.Equal(t, "http", repo.listWithFiltersProtocol)
  186. require.Equal(t, StatusActive, repo.listWithFiltersStatus)
  187. require.Equal(t, "p1", repo.listWithFiltersSearch)
  188. })
  189. }
  190. func TestAdminService_ListProxiesWithAccountCount_WithSearch(t *testing.T) {
  191. t.Run("search 参数正常传递到 repository 层", func(t *testing.T) {
  192. repo := &proxyRepoStubForAdminList{
  193. listWithFiltersAndAccountCountProxies: []ProxyWithAccountCount{{Proxy: Proxy{ID: 3, Name: "p2"}, AccountCount: 5}},
  194. listWithFiltersAndAccountCountResult: &pagination.PaginationResult{Total: 9},
  195. }
  196. svc := &adminServiceImpl{proxyRepo: repo}
  197. proxies, total, err := svc.ListProxiesWithAccountCount(context.Background(), 2, 10, "socks5", StatusDisabled, "p2", "account_count", "DESC")
  198. require.NoError(t, err)
  199. require.Equal(t, int64(9), total)
  200. require.Equal(t, []ProxyWithAccountCount{{Proxy: Proxy{ID: 3, Name: "p2"}, AccountCount: 5}}, proxies)
  201. require.Equal(t, 1, repo.listWithFiltersAndAccountCountCalls)
  202. require.Equal(t, pagination.PaginationParams{Page: 2, PageSize: 10, SortBy: "account_count", SortOrder: "DESC"}, repo.listWithFiltersAndAccountCountParams)
  203. require.Equal(t, "socks5", repo.listWithFiltersAndAccountCountProtocol)
  204. require.Equal(t, StatusDisabled, repo.listWithFiltersAndAccountCountStatus)
  205. require.Equal(t, "p2", repo.listWithFiltersAndAccountCountSearch)
  206. })
  207. }
  208. func TestAdminService_ListRedeemCodes_WithSearch(t *testing.T) {
  209. t.Run("search 参数正常传递到 repository 层", func(t *testing.T) {
  210. repo := &redeemRepoStubForAdminList{
  211. listWithFiltersCodes: []RedeemCode{{ID: 4, Code: "ABC"}},
  212. listWithFiltersResult: &pagination.PaginationResult{Total: 3},
  213. }
  214. svc := &adminServiceImpl{redeemCodeRepo: repo}
  215. codes, total, err := svc.ListRedeemCodes(context.Background(), 1, 20, RedeemTypeBalance, StatusUnused, "ABC", "value", "ASC")
  216. require.NoError(t, err)
  217. require.Equal(t, int64(3), total)
  218. require.Equal(t, []RedeemCode{{ID: 4, Code: "ABC"}}, codes)
  219. require.Equal(t, 1, repo.listWithFiltersCalls)
  220. require.Equal(t, pagination.PaginationParams{Page: 1, PageSize: 20, SortBy: "value", SortOrder: "ASC"}, repo.listWithFiltersParams)
  221. require.Equal(t, RedeemTypeBalance, repo.listWithFiltersType)
  222. require.Equal(t, StatusUnused, repo.listWithFiltersStatus)
  223. require.Equal(t, "ABC", repo.listWithFiltersSearch)
  224. })
  225. }