From d5cd8292eb9e2ae370a381fafa7eadde382e0e9c Mon Sep 17 00:00:00 2001 From: cita Date: Tue, 10 Mar 2026 16:12:38 +0800 Subject: [PATCH] test: cover model refresh early returns --- .../services/modelService.discovery.test.ts | 77 +++++++++++++++++++ src/server/services/modelService.ts | 49 +++++++++--- 2 files changed, 116 insertions(+), 10 deletions(-) diff --git a/src/server/services/modelService.discovery.test.ts b/src/server/services/modelService.discovery.test.ts index 8fd5350..1c41ae9 100644 --- a/src/server/services/modelService.discovery.test.ts +++ b/src/server/services/modelService.discovery.test.ts @@ -80,6 +80,8 @@ describe('refreshModelsForAccount credential discovery', () => { accountId: account.id, refreshed: true, status: 'success', + errorCode: null, + errorMessage: '', modelCount: 2, modelsPreview: ['claude-sonnet-4-5-20250929', 'claude-opus-4-6'], tokenScanned: 0, @@ -139,4 +141,79 @@ describe('refreshModelsForAccount credential discovery', () => { expect(parsed.runtimeHealth?.reason).toBe('模型获取失败,API Key 已无效'); expect(parsed.runtimeHealth?.checkedAt).toMatch(/\d{4}-\d{2}-\d{2}T/); }); + + it('returns structured result when account missing', async () => { + const result = await refreshModelsForAccount(9999); + + expect(result).toMatchObject({ + accountId: 9999, + refreshed: false, + status: 'failed', + errorCode: 'account_not_found', + errorMessage: '账号不存在', + modelCount: 0, + modelsPreview: [], + reason: 'account_not_found', + }); + }); + + it('returns structured result when site disabled', async () => { + const site = await db.insert(schema.sites).values({ + name: 'site-disabled', + url: 'https://site-disabled.example.com', + platform: 'new-api', + status: 'disabled', + }).returning().get(); + + const account = await db.insert(schema.accounts).values({ + siteId: site.id, + username: 'disabled-user', + accessToken: 'session-token', + apiToken: null, + status: 'active', + }).returning().get(); + + const result = await refreshModelsForAccount(account.id); + + expect(result).toMatchObject({ + accountId: account.id, + refreshed: false, + status: 'skipped', + errorCode: 'site_disabled', + errorMessage: '站点已禁用', + modelCount: 0, + modelsPreview: [], + reason: 'site_disabled', + }); + }); + + it('returns structured result when account inactive', async () => { + const site = await db.insert(schema.sites).values({ + name: 'site-inactive', + url: 'https://site-inactive.example.com', + platform: 'new-api', + status: 'active', + }).returning().get(); + + const account = await db.insert(schema.accounts).values({ + siteId: site.id, + username: 'inactive-user', + accessToken: 'session-token', + apiToken: null, + status: 'disabled', + }).returning().get(); + + const result = await refreshModelsForAccount(account.id); + + expect(result).toMatchObject({ + accountId: account.id, + refreshed: false, + status: 'skipped', + errorCode: 'adapter_or_status', + errorMessage: '平台不可用或账号未激活', + modelCount: 0, + modelsPreview: [], + reason: 'adapter_or_status', + }); + }); }); diff --git a/src/server/services/modelService.ts b/src/server/services/modelService.ts index 5f6a16a..fa97fce 100644 --- a/src/server/services/modelService.ts +++ b/src/server/services/modelService.ts @@ -70,9 +70,18 @@ export async function refreshModelsForAccount(accountId: number) { .where(eq(schema.accounts.id, accountId)) .get(); - if (!row) { - return { accountId, refreshed: false, modelCount: 0, reason: 'account_not_found' }; - } + if (!row) { + return { + accountId, + refreshed: false, + status: 'failed', + errorCode: 'account_not_found', + errorMessage: '账号不存在', + modelCount: 0, + modelsPreview: [], + reason: 'account_not_found', + }; + } const account = row.accounts; const site = row.sites; @@ -93,13 +102,31 @@ export async function refreshModelsForAccount(accountId: number) { .run(); } - if (isSiteDisabled(site.status)) { - return { accountId, refreshed: false, modelCount: 0, reason: 'site_disabled' }; - } - - if (!adapter || account.status !== 'active') { - return { accountId, refreshed: false, modelCount: 0, reason: 'adapter_or_status' }; - } + if (isSiteDisabled(site.status)) { + return { + accountId, + refreshed: false, + status: 'skipped', + errorCode: 'site_disabled', + errorMessage: '站点已禁用', + modelCount: 0, + modelsPreview: [], + reason: 'site_disabled', + }; + } + + if (!adapter || account.status !== 'active') { + return { + accountId, + refreshed: false, + status: 'skipped', + errorCode: 'adapter_or_status', + errorMessage: '平台不可用或账号未激活', + modelCount: 0, + modelsPreview: [], + reason: 'adapter_or_status', + }; + } const platformUserId = resolvePlatformUserId(account.extraConfig, account.username); let discoveredApiToken: string | null = null; @@ -278,6 +305,8 @@ export async function refreshModelsForAccount(accountId: number) { accountId, refreshed: true, status: 'success', + errorCode: null, + errorMessage: '', modelCount: accountModels.size, modelsPreview, tokenScanned: scannedTokenCount,