返回 AiToEarn
account.repository.spec.ts
根目录 / project / aitoearn-backend / libs / mongodb / src / repositories / account.repository.spec.ts
1 import type { Model } from 'mongoose'
2 import type { Account } from '../schemas'
3 import { AccountType } from '@yikart/common'
4 import { describe, expect, it, vi } from 'vitest'
5 import { ClientType } from '../schemas'
6 import { AccountRepository } from './account.repository'
7
8 vi.mock('../schemas', () => ({
9 Account: class Account {},
10 AccountStatus: {
11 NORMAL: 1,
12 ABNORMAL: 0,
13 },
14 ClientType: {
15 WEB: 'web',
16 APP: 'app',
17 },
18 }))
19
20 function createRepository() {
21 const exec = vi.fn(async () => ({ id: 'account-1' }))
22 const lean = vi.fn(() => ({ exec }))
23 const saved = {
24 toObject: vi.fn(() => ({ id: 'account-1' })),
25 }
26 const save = vi.fn(async () => saved)
27 const findOne = vi.fn(() => ({ lean }))
28 const findOneAndUpdate = vi.fn(() => ({ lean }))
29 const AccountModel = vi.fn(function AccountModel(this: { save: typeof save, data: unknown }, data: unknown) {
30 this.data = data
31 this.save = save
32 })
33 const model = Object.assign(AccountModel, {
34 findOne,
35 findOneAndUpdate,
36 })
37 const repository = new AccountRepository(model as unknown as Model<Account>)
38
39 return { repository, model, findOne, findOneAndUpdate, exec, lean, save, saved }
40 }
41
42 describe('account repository', () => {
43 it('gets accounts by the stable identity id or persisted identity fields', async () => {
44 const { repository, findOne } = createRepository()
45
46 await repository.getByIdentity({
47 type: AccountType.YouTube,
48 uid: 'google-user-id',
49 account: 'channel-id',
50 })
51
52 expect(findOne).toHaveBeenCalledWith({
53 $or: [
54 { _id: 'youtube_google-user-id_channel-id' },
55 {
56 type: AccountType.YouTube,
57 uid: 'google-user-id',
58 account: 'channel-id',
59 },
60 ],
61 })
62 })
63
64 it('keeps RedNote client type in identity field lookup', async () => {
65 const { repository, findOne } = createRepository()
66
67 await repository.getByIdentity({
68 type: AccountType.RedNote,
69 uid: 'rednote-user-id',
70 clientType: ClientType.WEB,
71 })
72
73 expect(findOne).toHaveBeenCalledWith({
74 $or: [
75 { _id: 'xhs_rednote-user-id_web' },
76 {
77 type: AccountType.RedNote,
78 uid: 'rednote-user-id',
79 account: null,
80 clientType: ClientType.WEB,
81 },
82 ],
83 })
84 })
85
86 it('creates accounts with the identity id and lets schema defaults apply', async () => {
87 const { repository, model, save, saved } = createRepository()
88
89 const result = await repository.createByIdentity(
90 { type: AccountType.YouTube, uid: 'google-user-id', account: 'channel-id' },
91 {
92 userId: 'user-1',
93 type: AccountType.YouTube,
94 uid: 'google-user-id',
95 account: 'channel-id',
96 nickname: 'Channel',
97 groupId: 'group-1',
98 },
99 )
100
101 expect(model).toHaveBeenCalledWith({
102 _id: 'youtube_google-user-id_channel-id',
103 userId: 'user-1',
104 type: AccountType.YouTube,
105 uid: 'google-user-id',
106 account: 'channel-id',
107 nickname: 'Channel',
108 groupId: 'group-1',
109 })
110 expect(save).toHaveBeenCalled()
111 expect(saved.toObject).toHaveBeenCalled()
112 expect(result).toEqual({ id: 'account-1' })
113 })
114
115 it('keeps the RedNote client type in the local identity id', async () => {
116 const { repository, model } = createRepository()
117
118 await repository.createByIdentity(
119 {
120 type: AccountType.RedNote,
121 uid: 'rednote-user-id',
122 clientType: ClientType.WEB,
123 },
124 {
125 userId: 'user-1',
126 type: AccountType.RedNote,
127 uid: 'rednote-user-id',
128 clientType: ClientType.WEB,
129 nickname: 'RedNote',
130 groupId: 'group-1',
131 },
132 )
133
134 expect(model).toHaveBeenCalledWith(expect.objectContaining({
135 _id: 'xhs_rednote-user-id_web',
136 clientType: 'web',
137 }))
138 })
139
140 it('updates existing accounts by the identity id or persisted identity fields', async () => {
141 const { repository, findOneAndUpdate } = createRepository()
142
143 await repository.updateByIdentity(
144 { type: AccountType.Twitter, uid: 'twitter-user-id' },
145 {
146 userId: 'user-1',
147 nickname: 'Twitter User',
148 },
149 )
150
151 expect(findOneAndUpdate).toHaveBeenCalledWith(
152 {
153 $or: [
154 { _id: 'twitter_twitter-user-id' },
155 {
156 type: AccountType.Twitter,
157 uid: 'twitter-user-id',
158 account: null,
159 },
160 ],
161 },
162 {
163 $set: {
164 userId: 'user-1',
165 nickname: 'Twitter User',
166 },
167 },
168 { new: true },
169 )
170 })
171 })
172
172 lines TYPESCRIPT