import { beforeEach, describe, expect, it, vi } from 'vitest' import { buildMockRequest } from '../helpers/request' import { installAuthMocks, mockAuthenticated, resetAuthMockState, } from '../helpers/auth' const prismaMock = vi.hoisted(() => ({ user: { findUnique: vi.fn<(...args: unknown[]) => Promise<{ id: string } | null>>(), }, userPreference: { findUnique: vi.fn<(...args: unknown[]) => Promise<{ customProviders: null; customModels: null } | null>>(), upsert: vi.fn<(...args: unknown[]) => Promise>(), }, })) const getBillingModeMock = vi.hoisted(() => vi.fn(async () => 'OFF')) vi.mock('@/lib/prisma', () => ({ prisma: prismaMock, })) vi.mock('@/lib/billing/mode', () => ({ getBillingMode: getBillingModeMock, })) describe('regression - persisted session user guard', () => { const routeContext = { params: Promise.resolve({}) } beforeEach(() => { vi.resetModules() vi.clearAllMocks() resetAuthMockState() installAuthMocks() mockAuthenticated('user-missing') prismaMock.user.findUnique.mockResolvedValue(null) prismaMock.userPreference.findUnique.mockResolvedValue({ customProviders: null, customModels: null, }) prismaMock.userPreference.upsert.mockResolvedValue({ id: 'pref-1' }) getBillingModeMock.mockResolvedValue('OFF') }) it('api-config PUT returns unauthorized before touching userPreference when session user row is missing', async () => { const route = await import('@/app/api/user/api-config/route') const req = buildMockRequest({ path: '/api/user/api-config', method: 'PUT', body: { providers: [ { id: 'openai-compatible:oa-1', name: 'OpenAI A', baseUrl: 'https://oa-a.test', apiKey: 'oa-key-a', }, ], }, }) const res = await route.PUT(req, routeContext) const body = await res.json() as { error?: { code?: string; message?: string } } expect(res.status).toBe(401) expect(body.error?.code).toBe('UNAUTHORIZED') expect(body.error?.message).toBe('登录状态已失效,请重新登录') expect(prismaMock.user.findUnique).toHaveBeenCalledWith({ where: { id: 'user-missing' }, select: { id: true }, }) expect(prismaMock.userPreference.findUnique).not.toHaveBeenCalled() expect(prismaMock.userPreference.upsert).not.toHaveBeenCalled() }) it('user-preference PATCH returns unauthorized before upsert when session user row is missing', async () => { const route = await import('@/app/api/user-preference/route') const req = buildMockRequest({ path: '/api/user-preference', method: 'PATCH', body: { artStyle: 'realistic' }, }) const res = await route.PATCH(req, routeContext) const body = await res.json() as { error?: { code?: string; message?: string } } expect(res.status).toBe(401) expect(body.error?.code).toBe('UNAUTHORIZED') expect(body.error?.message).toBe('登录状态已失效,请重新登录') expect(prismaMock.user.findUnique).toHaveBeenCalledWith({ where: { id: 'user-missing' }, select: { id: true }, }) expect(prismaMock.userPreference.upsert).not.toHaveBeenCalled() }) })