mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-02-05 21:13:07 +00:00
fix: resolve type errors from tags parameter change
Fixed type errors caused by changing WorkflowListParams.tags from string[] to string: 1. cleanup-helpers.ts: Changed tags: [tag] to tags: tag (line 221) 2. n8n-api-client.test.ts: Changed tags: ['test'] to tags: 'test,production' (line 384) 3. Added unit tests for handleDeleteWorkflow and handleListWorkflows (100% coverage) All tests pass, lint clean. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -218,7 +218,7 @@ export async function cleanupWorkflowsByTag(tag: string): Promise<string[]> {
|
||||
|
||||
try {
|
||||
const response = await client.listWorkflows({
|
||||
tags: tag ? [tag] : undefined,
|
||||
tags: tag || undefined,
|
||||
limit: 100,
|
||||
excludePinnedData: true
|
||||
});
|
||||
|
||||
@@ -723,6 +723,66 @@ describe('handlers-n8n-manager', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleDeleteWorkflow', () => {
|
||||
it('should delete workflow successfully', async () => {
|
||||
const testWorkflow = createTestWorkflow();
|
||||
mockApiClient.deleteWorkflow.mockResolvedValue(testWorkflow);
|
||||
|
||||
const result = await handlers.handleDeleteWorkflow({ id: 'test-workflow-id' });
|
||||
|
||||
expect(result).toEqual({
|
||||
success: true,
|
||||
data: testWorkflow,
|
||||
message: 'Workflow test-workflow-id deleted successfully',
|
||||
});
|
||||
expect(mockApiClient.deleteWorkflow).toHaveBeenCalledWith('test-workflow-id');
|
||||
});
|
||||
|
||||
it('should handle invalid input', async () => {
|
||||
const result = await handlers.handleDeleteWorkflow({ notId: 'test' });
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toBe('Invalid input');
|
||||
expect(result.details).toHaveProperty('errors');
|
||||
});
|
||||
|
||||
it('should handle N8nApiError', async () => {
|
||||
const apiError = new N8nNotFoundError('Workflow', 'non-existent-id');
|
||||
mockApiClient.deleteWorkflow.mockRejectedValue(apiError);
|
||||
|
||||
const result = await handlers.handleDeleteWorkflow({ id: 'non-existent-id' });
|
||||
|
||||
expect(result).toEqual({
|
||||
success: false,
|
||||
error: 'Workflow with ID non-existent-id not found',
|
||||
code: 'NOT_FOUND',
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle generic errors', async () => {
|
||||
const genericError = new Error('Database connection failed');
|
||||
mockApiClient.deleteWorkflow.mockRejectedValue(genericError);
|
||||
|
||||
const result = await handlers.handleDeleteWorkflow({ id: 'test-workflow-id' });
|
||||
|
||||
expect(result).toEqual({
|
||||
success: false,
|
||||
error: 'Database connection failed',
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle API not configured error', async () => {
|
||||
vi.mocked(getN8nApiConfig).mockReturnValue(null);
|
||||
|
||||
const result = await handlers.handleDeleteWorkflow({ id: 'test-workflow-id' });
|
||||
|
||||
expect(result).toEqual({
|
||||
success: false,
|
||||
error: 'n8n API not configured. Please set N8N_API_URL and N8N_API_KEY environment variables.',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleListWorkflows', () => {
|
||||
it('should list workflows with minimal data', async () => {
|
||||
const workflows = [
|
||||
@@ -770,6 +830,103 @@ describe('handlers-n8n-manager', () => {
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle invalid input with ZodError', async () => {
|
||||
const result = await handlers.handleListWorkflows({
|
||||
limit: 'invalid', // Should be a number
|
||||
});
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toBe('Invalid input');
|
||||
expect(result.details).toHaveProperty('errors');
|
||||
});
|
||||
|
||||
it('should handle N8nApiError', async () => {
|
||||
const apiError = new N8nAuthenticationError('Invalid API key');
|
||||
mockApiClient.listWorkflows.mockRejectedValue(apiError);
|
||||
|
||||
const result = await handlers.handleListWorkflows({});
|
||||
|
||||
expect(result).toEqual({
|
||||
success: false,
|
||||
error: 'Failed to authenticate with n8n. Please check your API key.',
|
||||
code: 'AUTHENTICATION_ERROR',
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle generic errors', async () => {
|
||||
const genericError = new Error('Network timeout');
|
||||
mockApiClient.listWorkflows.mockRejectedValue(genericError);
|
||||
|
||||
const result = await handlers.handleListWorkflows({});
|
||||
|
||||
expect(result).toEqual({
|
||||
success: false,
|
||||
error: 'Network timeout',
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle workflows without isArchived field gracefully', async () => {
|
||||
const workflows = [
|
||||
createTestWorkflow({ id: 'wf1', name: 'Workflow 1' }),
|
||||
];
|
||||
// Remove isArchived field to test undefined handling
|
||||
delete (workflows[0] as any).isArchived;
|
||||
|
||||
mockApiClient.listWorkflows.mockResolvedValue({
|
||||
data: workflows,
|
||||
nextCursor: null,
|
||||
});
|
||||
|
||||
const result = await handlers.handleListWorkflows({});
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data.workflows[0]).toHaveProperty('isArchived');
|
||||
});
|
||||
|
||||
it('should convert tags array to comma-separated string', async () => {
|
||||
const workflows = [
|
||||
createTestWorkflow({ id: 'wf1', name: 'Workflow 1', tags: ['tag1', 'tag2'] }),
|
||||
];
|
||||
|
||||
mockApiClient.listWorkflows.mockResolvedValue({
|
||||
data: workflows,
|
||||
nextCursor: null,
|
||||
});
|
||||
|
||||
const result = await handlers.handleListWorkflows({
|
||||
tags: ['production', 'active'],
|
||||
});
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(mockApiClient.listWorkflows).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
tags: 'production,active',
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle empty tags array', async () => {
|
||||
const workflows = [
|
||||
createTestWorkflow({ id: 'wf1', name: 'Workflow 1' }),
|
||||
];
|
||||
|
||||
mockApiClient.listWorkflows.mockResolvedValue({
|
||||
data: workflows,
|
||||
nextCursor: null,
|
||||
});
|
||||
|
||||
const result = await handlers.handleListWorkflows({
|
||||
tags: [],
|
||||
});
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(mockApiClient.listWorkflows).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
tags: undefined,
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleValidateWorkflow', () => {
|
||||
|
||||
@@ -381,12 +381,12 @@ describe('N8nApiClient', () => {
|
||||
});
|
||||
|
||||
it('should list workflows with custom params', async () => {
|
||||
const params = { limit: 10, active: true, tags: ['test'] };
|
||||
const params = { limit: 10, active: true, tags: 'test,production' };
|
||||
const response = { data: [], nextCursor: null };
|
||||
mockAxiosInstance.get.mockResolvedValue({ data: response });
|
||||
|
||||
|
||||
const result = await client.listWorkflows(params);
|
||||
|
||||
|
||||
expect(mockAxiosInstance.get).toHaveBeenCalledWith('/workflows', { params });
|
||||
expect(result).toEqual(response);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user