gongxiangp2/lib/__tests__/external-material-import-routes.test.ts
chenpei 4712175cb0 feat(素材链路): 发布白底图双轨与AI生图回传能力
- 完成白底图 WebP 双轨接口、上传链路与预览缓存改造
- 新增 AI 生图平台成品回传接口、任务状态与表单规则
- 补齐 AI 生成标签、任务详情补全、相关测试与对接文档
2026-03-25 10:28:02 +08:00

146 lines
4.6 KiB
TypeScript

/** @jest-environment node */
import { GET as getSchemaRoute } from '@/app/api/external/material-import/schema/route'
import { POST as postJobsRoute } from '@/app/api/external/material-import/jobs/route'
import { GET as getJobStatusRoute } from '@/app/api/external/material-import/jobs/[jobId]/route'
import { getExternalMaterialImportJobStatus, getExternalMaterialImportSchema, createExternalMaterialImportJob, triggerExternalMaterialImportJob } from '@/lib/external-material-import'
import { logApiCall, validateApiKey } from '@/lib/external-api'
jest.mock('@/lib/external-api', () => {
const { NextResponse } = require('next/server')
return {
getApiKeyFromRequest: jest.fn((request: { headers: Headers }) => request.headers.get('X-API-Key')),
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/external-material-import', () => ({
ExternalMaterialImportError: class ExternalMaterialImportError extends Error {
status: number
code: string
constructor(status: number, code: string, message: string) {
super(message)
this.status = status
this.code = code
}
},
getExternalMaterialImportSchema: jest.fn(),
createExternalMaterialImportJob: jest.fn(),
getExternalMaterialImportJobStatus: jest.fn(),
triggerExternalMaterialImportJob: jest.fn(),
}))
function createRequest(url: string, body?: unknown) {
return {
nextUrl: new URL(url),
headers: new Headers({
'X-API-Key': 'test-key',
'user-agent': 'jest',
}),
json: jest.fn().mockResolvedValue(body),
} as any
}
describe('external material import routes', () => {
beforeEach(() => {
jest.clearAllMocks()
;(validateApiKey as jest.Mock).mockResolvedValue({
id: 'api-1',
name: 'test-key',
isActive: true,
})
})
test('schema 路由应返回服务层 schema 结果', async () => {
;(getExternalMaterialImportSchema as jest.Mock).mockResolvedValue({
materialType: '任务-详情',
open: true,
fields: [],
imageGroups: {
allowedKeys: ['main', 'sku', 'detail'],
minTotalImages: 1,
},
})
const response = await getSchemaRoute(
createRequest('https://example.com/api/external/material-import/schema?materialType=任务-详情'),
)
const body = await response.json()
expect(response.status).toBe(200)
expect(body.success).toBe(true)
expect(body.data.materialType).toBe('任务-详情')
expect(getExternalMaterialImportSchema).toHaveBeenCalledWith('任务-详情')
expect(logApiCall).toHaveBeenCalled()
})
test('jobs 路由创建新任务时应触发后台处理', async () => {
;(createExternalMaterialImportJob as jest.Mock).mockResolvedValue({
created: true,
job: {
jobId: 'job-1',
materialType: '任务-详情',
taskNo: 'TASK202603240001',
status: 'processing',
success: false,
resultMaterialId: null,
errorCode: null,
errorMessage: null,
completedAt: null,
},
})
const response = await postJobsRoute(
createRequest('https://example.com/api/external/material-import/jobs', {
formData: {
taskNo: 'TASK202603240001',
},
}),
)
const body = await response.json()
expect(response.status).toBe(200)
expect(body.success).toBe(true)
expect(body.data.created).toBe(true)
expect(triggerExternalMaterialImportJob).toHaveBeenCalledWith('job-1')
})
test('job status 路由应透传 jobId 和 apiKey 范围查询', async () => {
;(getExternalMaterialImportJobStatus as jest.Mock).mockResolvedValue({
jobId: 'job-1',
materialType: '任务-详情',
taskNo: 'TASK202603240001',
status: 'succeeded',
success: true,
resultMaterialId: 'material-1',
errorCode: null,
errorMessage: null,
completedAt: '2026-03-24T09:02:00.000Z',
})
const response = await getJobStatusRoute(
createRequest('https://example.com/api/external/material-import/jobs/job-1'),
{ params: { jobId: 'job-1' } },
)
const body = await response.json()
expect(response.status).toBe(200)
expect(body.success).toBe(true)
expect(body.data.success).toBe(true)
expect(getExternalMaterialImportJobStatus).toHaveBeenCalledWith({
apiKeyId: 'api-1',
jobId: 'job-1',
})
})
})