/** @jest-environment node */ import { GET } from '@/app/api/external/dingtalk-material-options/route' import { prisma } from '@/lib/prisma' import { logApiCall, validateApiKey } from '@/lib/external-api' jest.mock('@/lib/external-api', () => { const { NextResponse } = require('next/server') return { getApiKeyFromRequest: jest.fn( (request: { headers: Headers; nextUrl: URL }, options?: { allowQuery?: boolean }) => request.headers.get('X-API-Key') || (options?.allowQuery ? request.nextUrl.searchParams.get('apiKey') : null), ), getClientIp: jest.fn(() => '127.0.0.1'), logApiCall: jest.fn().mockResolvedValue(undefined), successResponse: jest.fn((data: unknown, message?: string) => NextResponse.json({ success: true, ...(message ? { message } : {}), data, }), ), validateApiKey: jest.fn(), } }) jest.mock('@/lib/prisma', () => ({ prisma: { category: { findMany: jest.fn(), }, scene: { findMany: jest.fn(), }, productCategory: { findMany: jest.fn(), }, }, })) describe('external dingtalk-material-options route', () => { beforeEach(() => { jest.clearAllMocks() ;(validateApiKey as jest.Mock).mockResolvedValue({ id: 'api-key-1', name: 'test-key', isActive: true, }) ;(prisma.category.findMany as jest.Mock).mockResolvedValue([ { name: '顾家家居' }, { name: '林氏木业' }, ]) ;(prisma.scene.findMany as jest.Mock).mockResolvedValue([ { name: '客厅' }, { name: '卧室' }, ]) ;(prisma.productCategory.findMany as jest.Mock).mockResolvedValue([ { name: '沙发' }, { name: '床' }, ]) }) function createRequest(url: string, apiKey = 'test-key') { return { nextUrl: new URL(url), headers: new Headers({ ...(apiKey ? { 'X-API-Key': apiKey } : {}), 'user-agent': 'jest', }), } as any } test('应返回钉钉下拉选项', async () => { const response = await GET(createRequest('https://example.com/api/external/dingtalk-material-options')) const body = await response.json() expect(response.status).toBe(200) expect(body.success).toBe(true) expect(body.data.requirementTypes).toContain('任务-详情') expect(body.data.brands).toEqual(['顾家家居', '林氏木业']) expect(body.data.sceneCategories).toEqual(['客厅', '卧室']) expect(body.data.productCategories).toEqual(['沙发', '床']) expect(logApiCall).toHaveBeenCalled() }) test('允许钉钉用固定 URL 参数传 apiKey,避免每次手填请求头', async () => { const response = await GET( createRequest('https://example.com/api/external/dingtalk-material-options?apiKey=test-key', ''), ) expect(response.status).toBe(200) expect(validateApiKey).toHaveBeenCalledWith('test-key') }) })