106 lines
3.1 KiB
TypeScript
106 lines
3.1 KiB
TypeScript
const mockInsert = jest.fn().mockReturnValue({
|
|
values: jest.fn().mockResolvedValue(undefined),
|
|
});
|
|
|
|
jest.mock('@/db', () => ({
|
|
db: {
|
|
insert: mockInsert,
|
|
},
|
|
}));
|
|
|
|
jest.mock('nanoid', () => ({
|
|
nanoid: jest.fn(() => 'test-id'),
|
|
}));
|
|
|
|
import { createAuditLog, getActionLabel, getActionColor } from './audit';
|
|
|
|
describe('audit', () => {
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
describe('createAuditLog', () => {
|
|
it('should create audit log successfully', async () => {
|
|
const mockValues = jest.fn().mockResolvedValue(undefined);
|
|
mockInsert.mockReturnValue({ values: mockValues });
|
|
|
|
const logData = {
|
|
userId: 'user-123',
|
|
action: 'LOGIN',
|
|
details: { ip: '192.168.1.1' },
|
|
};
|
|
|
|
await createAuditLog(logData);
|
|
|
|
expect(mockValues).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
id: 'test-id',
|
|
userId: 'user-123',
|
|
action: 'LOGIN',
|
|
details: { ip: '192.168.1.1' },
|
|
timestamp: expect.any(Date),
|
|
})
|
|
);
|
|
});
|
|
|
|
it('should handle missing optional fields', async () => {
|
|
const mockValues = jest.fn().mockResolvedValue(undefined);
|
|
mockInsert.mockReturnValue({ values: mockValues });
|
|
|
|
const logData = {
|
|
userId: 'user-456',
|
|
action: 'LOGOUT',
|
|
};
|
|
|
|
await createAuditLog(logData);
|
|
|
|
expect(mockValues).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
id: 'test-id',
|
|
userId: 'user-456',
|
|
action: 'LOGOUT',
|
|
timestamp: expect.any(Date),
|
|
})
|
|
);
|
|
});
|
|
|
|
it('should handle database errors gracefully', async () => {
|
|
const mockValues = jest.fn().mockRejectedValue(new Error('Database error'));
|
|
mockInsert.mockReturnValue({ values: mockValues });
|
|
|
|
const consoleSpy = jest.spyOn(console, 'error').mockImplementation();
|
|
|
|
await createAuditLog({
|
|
userId: 'user-789',
|
|
action: 'LOGIN',
|
|
});
|
|
|
|
expect(consoleSpy).toHaveBeenCalled();
|
|
consoleSpy.mockRestore();
|
|
});
|
|
});
|
|
|
|
describe('getActionLabel', () => {
|
|
it('should return correct label for known actions', () => {
|
|
expect(getActionLabel('login')).toBe('登录');
|
|
expect(getActionLabel('logout')).toBe('登出');
|
|
expect(getActionLabel('create')).toBe('创建');
|
|
expect(getActionLabel('update')).toBe('更新');
|
|
expect(getActionLabel('delete')).toBe('删除');
|
|
expect(getActionLabel('publish')).toBe('发布');
|
|
expect(getActionLabel('upload')).toBe('上传');
|
|
});
|
|
});
|
|
|
|
describe('getActionColor', () => {
|
|
it('should return correct color for known actions', () => {
|
|
expect(getActionColor('login')).toBe('bg-cyan-100 text-cyan-800');
|
|
expect(getActionColor('logout')).toBe('bg-gray-100 text-gray-800');
|
|
expect(getActionColor('create')).toBe('bg-green-100 text-green-800');
|
|
expect(getActionColor('update')).toBe('bg-blue-100 text-blue-800');
|
|
expect(getActionColor('delete')).toBe('bg-red-100 text-red-800');
|
|
expect(getActionColor('publish')).toBe('bg-purple-100 text-purple-800');
|
|
expect(getActionColor('upload')).toBe('bg-yellow-100 text-yellow-800');
|
|
});
|
|
});
|
|
}); |