| const { duplicateAgent } = require('../v1'); | |
| const { getAgent, createAgent } = require('~/models/Agent'); | |
| const { getActions } = require('~/models/Action'); | |
| const { nanoid } = require('nanoid'); | |
| jest.mock('~/models/Agent'); | |
| jest.mock('~/models/Action'); | |
| jest.mock('nanoid'); | |
| describe('duplicateAgent', () => { | |
| let req, res; | |
| beforeEach(() => { | |
| req = { | |
| params: { id: 'agent_123' }, | |
| user: { id: 'user_456' }, | |
| }; | |
| res = { | |
| status: jest.fn().mockReturnThis(), | |
| json: jest.fn(), | |
| }; | |
| jest.clearAllMocks(); | |
| }); | |
| it('should duplicate an agent successfully', async () => { | |
| const mockAgent = { | |
| id: 'agent_123', | |
| name: 'Test Agent', | |
| description: 'Test Description', | |
| instructions: 'Test Instructions', | |
| provider: 'openai', | |
| model: 'gpt-4', | |
| tools: ['file_search'], | |
| actions: [], | |
| author: 'user_789', | |
| versions: [{ name: 'Test Agent', version: 1 }], | |
| __v: 0, | |
| }; | |
| const mockNewAgent = { | |
| id: 'agent_new_123', | |
| name: 'Test Agent (1/2/23, 12:34)', | |
| description: 'Test Description', | |
| instructions: 'Test Instructions', | |
| provider: 'openai', | |
| model: 'gpt-4', | |
| tools: ['file_search'], | |
| actions: [], | |
| author: 'user_456', | |
| versions: [ | |
| { | |
| name: 'Test Agent (1/2/23, 12:34)', | |
| description: 'Test Description', | |
| instructions: 'Test Instructions', | |
| provider: 'openai', | |
| model: 'gpt-4', | |
| tools: ['file_search'], | |
| actions: [], | |
| createdAt: new Date(), | |
| updatedAt: new Date(), | |
| }, | |
| ], | |
| }; | |
| getAgent.mockResolvedValue(mockAgent); | |
| getActions.mockResolvedValue([]); | |
| nanoid.mockReturnValue('new_123'); | |
| createAgent.mockResolvedValue(mockNewAgent); | |
| await duplicateAgent(req, res); | |
| expect(getAgent).toHaveBeenCalledWith({ id: 'agent_123' }); | |
| expect(getActions).toHaveBeenCalledWith({ agent_id: 'agent_123' }, true); | |
| expect(createAgent).toHaveBeenCalledWith( | |
| expect.objectContaining({ | |
| id: 'agent_new_123', | |
| author: 'user_456', | |
| name: expect.stringContaining('Test Agent ('), | |
| description: 'Test Description', | |
| instructions: 'Test Instructions', | |
| provider: 'openai', | |
| model: 'gpt-4', | |
| tools: ['file_search'], | |
| actions: [], | |
| }), | |
| ); | |
| expect(createAgent).toHaveBeenCalledWith( | |
| expect.not.objectContaining({ | |
| versions: expect.anything(), | |
| __v: expect.anything(), | |
| }), | |
| ); | |
| expect(res.status).toHaveBeenCalledWith(201); | |
| expect(res.json).toHaveBeenCalledWith({ | |
| agent: mockNewAgent, | |
| actions: [], | |
| }); | |
| }); | |
| it('should ensure duplicated agent has clean versions array without nested fields', async () => { | |
| const mockAgent = { | |
| id: 'agent_123', | |
| name: 'Test Agent', | |
| description: 'Test Description', | |
| versions: [ | |
| { | |
| name: 'Test Agent', | |
| versions: [{ name: 'Nested' }], | |
| __v: 1, | |
| }, | |
| ], | |
| __v: 2, | |
| }; | |
| const mockNewAgent = { | |
| id: 'agent_new_123', | |
| name: 'Test Agent (1/2/23, 12:34)', | |
| description: 'Test Description', | |
| versions: [ | |
| { | |
| name: 'Test Agent (1/2/23, 12:34)', | |
| description: 'Test Description', | |
| createdAt: new Date(), | |
| updatedAt: new Date(), | |
| }, | |
| ], | |
| }; | |
| getAgent.mockResolvedValue(mockAgent); | |
| getActions.mockResolvedValue([]); | |
| nanoid.mockReturnValue('new_123'); | |
| createAgent.mockResolvedValue(mockNewAgent); | |
| await duplicateAgent(req, res); | |
| expect(mockNewAgent.versions).toHaveLength(1); | |
| const firstVersion = mockNewAgent.versions[0]; | |
| expect(firstVersion).not.toHaveProperty('versions'); | |
| expect(firstVersion).not.toHaveProperty('__v'); | |
| expect(mockNewAgent).not.toHaveProperty('__v'); | |
| expect(res.status).toHaveBeenCalledWith(201); | |
| }); | |
| it('should return 404 if agent not found', async () => { | |
| getAgent.mockResolvedValue(null); | |
| await duplicateAgent(req, res); | |
| expect(res.status).toHaveBeenCalledWith(404); | |
| expect(res.json).toHaveBeenCalledWith({ | |
| error: 'Agent not found', | |
| status: 'error', | |
| }); | |
| }); | |
| it('should convert `tool_resources.ocr` to `tool_resources.context`', async () => { | |
| const mockAgent = { | |
| id: 'agent_123', | |
| name: 'Test Agent', | |
| tool_resources: { | |
| ocr: { enabled: true, config: 'test' }, | |
| other: { should: 'not be copied' }, | |
| }, | |
| }; | |
| getAgent.mockResolvedValue(mockAgent); | |
| getActions.mockResolvedValue([]); | |
| nanoid.mockReturnValue('new_123'); | |
| createAgent.mockResolvedValue({ id: 'agent_new_123' }); | |
| await duplicateAgent(req, res); | |
| expect(createAgent).toHaveBeenCalledWith( | |
| expect.objectContaining({ | |
| tool_resources: { | |
| context: { enabled: true, config: 'test' }, | |
| }, | |
| }), | |
| ); | |
| }); | |
| it('should handle errors gracefully', async () => { | |
| getAgent.mockRejectedValue(new Error('Database error')); | |
| await duplicateAgent(req, res); | |
| expect(res.status).toHaveBeenCalledWith(500); | |
| expect(res.json).toHaveBeenCalledWith({ error: 'Database error' }); | |
| }); | |
| }); | |