Skip to content

Commit 6132fa4

Browse files
committed
test: 修复账号共享与前端模型用量验证
同步账号共享仓储 sqlmock 列清单,覆盖新增 proxy_id 扫描字段,恢复 UpdateListing 相关单元测试。 为认证来源默认值 helper 补齐 GitHub/Google 缺失场景的默认归一化,并扩展设置 API 测试断言。 补齐批量编辑测试的 auth store mock,更新 Antigravity/Gemini 图片模型白名单预期,并在账号用量单元格中聚合 Gemini 图片模型配额展示。 验证:go test ./...;pnpm test:run;pnpm build。
1 parent a35a8e0 commit 6132fa4

6 files changed

Lines changed: 72 additions & 14 deletions

File tree

backend/internal/repository/account_share_mode_repo_unit_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func TestAccountShareModeRepositoryUpdateListingRequiresOwnerForUser(t *testing.
2424
mock.ExpectBegin()
2525
mock.ExpectQuery("SELECT l\\.account_id, l\\.owner_user_id, l\\.seat_limit, l\\.per_user_concurrency, a\\.concurrency").
2626
WithArgs(int64(7), int64(42)).
27-
WillReturnRows(sqlmock.NewRows([]string{"account_id", "owner_user_id", "seat_limit", "per_user_concurrency", "concurrency", "edit_session_id", "editing_by_user_id", "editing_expires_at"}))
27+
WillReturnRows(sqlmock.NewRows([]string{"account_id", "owner_user_id", "seat_limit", "per_user_concurrency", "concurrency", "proxy_id", "edit_session_id", "editing_by_user_id", "editing_expires_at"}))
2828
mock.ExpectRollback()
2929

3030
status := service.AccountShareListingStatusPaused
@@ -49,8 +49,8 @@ func TestAccountShareModeRepositoryUpdateListingAllowsAdminWithoutOwnerFilter(t
4949
mock.ExpectBegin()
5050
mock.ExpectQuery("SELECT l\\.account_id, l\\.owner_user_id, l\\.seat_limit, l\\.per_user_concurrency, a\\.concurrency").
5151
WithArgs(int64(7)).
52-
WillReturnRows(sqlmock.NewRows([]string{"account_id", "owner_user_id", "seat_limit", "per_user_concurrency", "concurrency", "edit_session_id", "editing_by_user_id", "editing_expires_at"}).
53-
AddRow(int64(99), int64(50), 2, 5, 20, nil, nil, nil))
52+
WillReturnRows(sqlmock.NewRows([]string{"account_id", "owner_user_id", "seat_limit", "per_user_concurrency", "concurrency", "proxy_id", "edit_session_id", "editing_by_user_id", "editing_expires_at"}).
53+
AddRow(int64(99), int64(50), 2, 5, 20, nil, nil, nil, nil))
5454
mock.ExpectExec("UPDATE account_share_listings").
5555
WithArgs(service.AccountShareListingStatusPaused, int64(7)).
5656
WillReturnError(updateErr)
@@ -79,8 +79,8 @@ func TestAccountShareModeRepositoryUpdateListingSyncsAllowedModelsToAccount(t *t
7979
mock.ExpectBegin()
8080
mock.ExpectQuery("SELECT l\\.account_id, l\\.owner_user_id, l\\.seat_limit, l\\.per_user_concurrency, a\\.concurrency").
8181
WithArgs(int64(7), int64(42)).
82-
WillReturnRows(sqlmock.NewRows([]string{"account_id", "owner_user_id", "seat_limit", "per_user_concurrency", "concurrency", "edit_session_id", "editing_by_user_id", "editing_expires_at"}).
83-
AddRow(int64(99), int64(42), 2, 5, 20, nil, nil, nil))
82+
WillReturnRows(sqlmock.NewRows([]string{"account_id", "owner_user_id", "seat_limit", "per_user_concurrency", "concurrency", "proxy_id", "edit_session_id", "editing_by_user_id", "editing_expires_at"}).
83+
AddRow(int64(99), int64(42), 2, 5, 20, nil, nil, nil, nil))
8484
mock.ExpectExec("UPDATE account_share_listings").
8585
WithArgs(`["gpt-5.5","gpt-5.4"]`, int64(7), int64(42)).
8686
WillReturnResult(sqlmock.NewResult(0, 1))

frontend/src/api/__tests__/settings.authSourceDefaults.spec.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,20 @@ describe("admin settings auth source defaults helpers", () => {
9898
grant_on_signup: false,
9999
grant_on_first_bind: false,
100100
},
101+
github: {
102+
balance: 3,
103+
concurrency: 4,
104+
subscriptions: [{ group_id: 10, validity_days: 14 }],
105+
grant_on_signup: true,
106+
grant_on_first_bind: false,
107+
},
108+
google: {
109+
balance: 0,
110+
concurrency: 5,
111+
subscriptions: [],
112+
grant_on_signup: false,
113+
grant_on_first_bind: true,
114+
},
101115
});
102116

103117
expect(payload).toMatchObject({
@@ -126,6 +140,18 @@ describe("admin settings auth source defaults helpers", () => {
126140
auth_source_default_wechat_subscriptions: [],
127141
auth_source_default_wechat_grant_on_signup: false,
128142
auth_source_default_wechat_grant_on_first_bind: false,
143+
auth_source_default_github_balance: 3,
144+
auth_source_default_github_concurrency: 4,
145+
auth_source_default_github_subscriptions: [
146+
{ group_id: 10, validity_days: 14 },
147+
],
148+
auth_source_default_github_grant_on_signup: true,
149+
auth_source_default_github_grant_on_first_bind: false,
150+
auth_source_default_google_balance: 0,
151+
auth_source_default_google_concurrency: 5,
152+
auth_source_default_google_subscriptions: [],
153+
auth_source_default_google_grant_on_signup: false,
154+
auth_source_default_google_grant_on_first_bind: true,
129155
});
130156
});
131157
});

frontend/src/api/admin/settings.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,16 @@ const WECHAT_CONNECT_MODE_ALIASES: Record<string, WeChatConnectMode> = {
142142
native_app: "mobile",
143143
};
144144

145+
function createDefaultAuthSourceDefaultsValue(): AuthSourceDefaultsValue {
146+
return {
147+
balance: AUTH_SOURCE_DEFAULT_BALANCE,
148+
concurrency: AUTH_SOURCE_DEFAULT_CONCURRENCY,
149+
subscriptions: [],
150+
grant_on_signup: false,
151+
grant_on_first_bind: false,
152+
};
153+
}
154+
145155
export function normalizeDefaultSubscriptionSettings(
146156
subscriptions: DefaultSubscriptionSetting[] | null | undefined,
147157
): DefaultSubscriptionSetting[] {
@@ -193,12 +203,13 @@ export function buildAuthSourceDefaultsState(
193203

194204
export function appendAuthSourceDefaultsToUpdateRequest(
195205
payload: UpdateSettingsRequest,
196-
authSourceDefaults: AuthSourceDefaultsState,
206+
authSourceDefaults: Partial<AuthSourceDefaultsState>,
197207
): UpdateSettingsRequest {
198208
const target = payload as Record<string, unknown>;
199209

200210
for (const source of AUTH_SOURCE_TYPES) {
201-
const current = authSourceDefaults[source];
211+
const current =
212+
authSourceDefaults[source] ?? createDefaultAuthSourceDefaultsValue();
202213
target[`auth_source_default_${source}_balance`] =
203214
Number(current.balance) || 0;
204215
target[`auth_source_default_${source}_concurrency`] = Math.max(

frontend/src/components/account/AccountUsageCell.vue

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,15 @@
263263
color="emerald"
264264
/>
265265

266+
<!-- Gemini Image -->
267+
<UsageProgressBar
268+
v-if="antigravityImageUsageFromAPI !== null"
269+
:label="t('admin.accounts.usageWindow.gemini3Image')"
270+
:utilization="antigravityImageUsageFromAPI.utilization"
271+
:resets-at="antigravityImageUsageFromAPI.resetTime"
272+
color="purple"
273+
/>
274+
266275
<!-- Claude -->
267276
<UsageProgressBar
268277
v-if="antigravityClaudeUsageFromAPI !== null"
@@ -644,6 +653,11 @@ const antigravity3ProUsageFromAPI = computed(() =>
644653
// Gemini 3 Flash from API
645654
const antigravity3FlashUsageFromAPI = computed(() => getAntigravityUsageFromAPI(['gemini-3-flash']))
646655
656+
// Gemini image quota from API
657+
const antigravityImageUsageFromAPI = computed(() =>
658+
getAntigravityUsageFromAPI(['gemini-3.1-flash-image', 'gemini-2.5-flash-image', 'gemini-3-pro-image'])
659+
)
660+
647661
// Claude from API (all Claude model variants)
648662
const antigravityClaudeUsageFromAPI = computed(() =>
649663
getAntigravityUsageFromAPI([

frontend/src/components/account/__tests__/BulkEditAccountModal.spec.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ vi.mock('@/stores/app', () => ({
1313
})
1414
}))
1515

16+
vi.mock('@/stores/auth', () => ({
17+
useAuthStore: () => ({
18+
refreshUser: vi.fn().mockResolvedValue(undefined)
19+
})
20+
}))
21+
1622
vi.mock('@/api/admin', () => ({
1723
adminAPI: {
1824
accounts: {

frontend/src/composables/__tests__/useModelWhitelist.spec.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,24 @@ describe('useModelWhitelist', () => {
2929
it('antigravity 模型列表包含图片模型兼容项', () => {
3030
const models = getModelsByPlatform('antigravity')
3131

32-
expect(models).not.toContain('gemini-2.5-flash-image')
33-
expect(models).not.toContain('gemini-3.1-flash-image')
34-
expect(models).not.toContain('gemini-3-pro-image')
32+
expect(models).toContain('gemini-2.5-flash-image')
33+
expect(models).toContain('gemini-3.1-flash-image')
34+
expect(models).toContain('gemini-3-pro-image')
3535
})
3636

3737
it('gemini 模型列表包含原生生图模型', () => {
3838
const models = getModelsByPlatform('gemini')
3939

40-
expect(models).not.toContain('gemini-2.5-flash-image')
41-
expect(models).not.toContain('gemini-3.1-flash-image')
40+
expect(models).toContain('gemini-2.5-flash-image')
41+
expect(models).toContain('gemini-3.1-flash-image')
4242
})
4343

4444
it('antigravity 模型列表会把新的 Gemini 图片模型排在前面', () => {
4545
const models = getModelsByPlatform('antigravity')
4646

47-
expect(models).not.toContain('gemini-3.1-flash-image')
48-
expect(models).not.toContain('gemini-2.5-flash-image')
47+
expect(models.indexOf('gemini-3.1-flash-image')).toBeLessThan(
48+
models.indexOf('gemini-2.5-flash-image')
49+
)
4950
})
5051

5152
it('whitelist 模式会忽略通配符条目', () => {

0 commit comments

Comments
 (0)