2026-06-03 18:41:52 +08:00

98 lines
3.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { NextRequest } from 'next/server';
import { POST } from '../route';
import { updatePremiumModuleRuntimeStatus } from '@/lib/license/premium-module-service';
jest.mock('@/lib/license/premium-module-service', () => ({
PREMIUM_MODULE_IDS: {
PAID_CORE: 'paid-core',
},
updatePremiumModuleRuntimeStatus: jest.fn(),
}));
const mockUpdatePremiumModuleRuntimeStatus =
updatePremiumModuleRuntimeStatus as jest.MockedFunction<typeof updatePremiumModuleRuntimeStatus>;
function createRequest(body: Record<string, unknown>, token = 'a'.repeat(32)) {
return new NextRequest('http://localhost/api/license/premium-modules/runtime-status', {
method: 'POST',
headers: {
authorization: `Bearer ${token}`,
},
body: JSON.stringify(body),
});
}
describe('POST /api/license/premium-modules/runtime-status', () => {
beforeEach(() => {
jest.clearAllMocks();
process.env.MODULE_RUNTIME_STATUS_TOKEN = 'a'.repeat(32);
delete process.env.FLNXI_MODULE_STATUS_CALLBACK_TOKEN;
});
afterEach(() => {
delete process.env.MODULE_RUNTIME_STATUS_TOKEN;
delete process.env.FLNXI_MODULE_STATUS_CALLBACK_TOKEN;
});
it('需要回写 token,避免公开接口被任意写入模块运行态', async () => {
const response = await POST(createRequest({
moduleId: 'paid-core',
image: 'registry.test/flnxi/premium/paid-core:1.0.0',
status: 'running',
lastSyncAt: new Date().toISOString(),
}, 'wrong-token'));
expect(response.status).toBe(401);
expect(mockUpdatePremiumModuleRuntimeStatus).not.toHaveBeenCalled();
});
it('token 未配置时默认关闭回写入口', async () => {
delete process.env.MODULE_RUNTIME_STATUS_TOKEN;
const response = await POST(createRequest({
moduleId: 'paid-core',
image: 'registry.test/flnxi/premium/paid-core:1.0.0',
status: 'running',
lastSyncAt: new Date().toISOString(),
}));
expect(response.status).toBe(503);
expect(mockUpdatePremiumModuleRuntimeStatus).not.toHaveBeenCalled();
});
it('接受 Agent 上报的合法模块运行状态并持久化', async () => {
const lastSyncAt = new Date().toISOString();
const response = await POST(createRequest({
moduleId: 'paid-core',
image: 'registry.test/flnxi/premium/paid-core:1.0.0',
digest: 'sha256:' + 'a'.repeat(64),
status: 'running',
lastSyncAt,
}));
const data = await response.json();
expect(response.status).toBe(200);
expect(data).toEqual({ success: true, updated: 1 });
expect(mockUpdatePremiumModuleRuntimeStatus).toHaveBeenCalledWith({
moduleId: 'paid-core',
image: 'registry.test/flnxi/premium/paid-core:1.0.0',
digest: 'sha256:' + 'a'.repeat(64),
status: 'running',
lastSyncAt,
lastError: undefined,
});
});
it('拒绝未知模块或非法状态', async () => {
const response = await POST(createRequest({
moduleId: 'unknown-module',
image: 'registry.test/flnxi/premium/unknown:1.0.0',
status: 'running',
lastSyncAt: new Date().toISOString(),
}));
expect(response.status).toBe(400);
expect(mockUpdatePremiumModuleRuntimeStatus).not.toHaveBeenCalled();
});
});