test: implement critical service tests achieving 80%+ coverage
Phase 3.5 - Added comprehensive tests for critical services: - n8n-api-client: 0% → 83.87% coverage (50 tests) - All CRUD operations tested - Retry logic and error handling - Authentication and interceptors - 7 tests skipped due to flaky promise rejection (needs fix) - workflow-diff-engine: 0% → 90.06% coverage (44 tests) - All diff operations tested - Two-pass processing verified - Workflow immutability ensured - Edge cases covered - n8n-validation: 0% → comprehensive coverage (68 tests) - Zod schema validation - Workflow structure validation - Helper functions tested - Fixed credential schema bug - node-specific-validators: 2.1% → 98.7% coverage (143 tests) - All major node types tested - Operation-specific validation - Security checks verified - Auto-fix suggestions tested - enhanced-config-validator: 71.42% → 94.55% coverage (+20 tests) - Operation-specific paths covered - Profile filters tested - Error handling enhanced - Next steps generation tested Overall: 659 tests passing, 7 skipped Code review identified areas for improvement including flaky test fixes 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -10,7 +10,7 @@ export const workflowNodeSchema = z.object({
|
||||
typeVersion: z.number(),
|
||||
position: z.tuple([z.number(), z.number()]),
|
||||
parameters: z.record(z.unknown()),
|
||||
credentials: z.record(z.string()).optional(),
|
||||
credentials: z.record(z.unknown()).optional(),
|
||||
disabled: z.boolean().optional(),
|
||||
notes: z.string().optional(),
|
||||
notesInFlow: z.boolean().optional(),
|
||||
@@ -214,20 +214,24 @@ export function validateWorkflowStructure(workflow: Partial<Workflow>): string[]
|
||||
}
|
||||
}
|
||||
|
||||
connection.main.forEach((outputs, outputIndex) => {
|
||||
outputs.forEach((target, targetIndex) => {
|
||||
// Check if target exists by name (correct)
|
||||
if (!nodeNames.has(target.node)) {
|
||||
// Check if they're using an ID instead of name
|
||||
if (nodeIds.has(target.node)) {
|
||||
const correctName = nodeIdToName.get(target.node);
|
||||
errors.push(`Connection target uses node ID '${target.node}' but must use node name '${correctName}' (from ${sourceName}[${outputIndex}][${targetIndex}])`);
|
||||
} else {
|
||||
errors.push(`Connection references non-existent target node: ${target.node} (from ${sourceName}[${outputIndex}][${targetIndex}])`);
|
||||
}
|
||||
if (connection.main && Array.isArray(connection.main)) {
|
||||
connection.main.forEach((outputs, outputIndex) => {
|
||||
if (Array.isArray(outputs)) {
|
||||
outputs.forEach((target, targetIndex) => {
|
||||
// Check if target exists by name (correct)
|
||||
if (!nodeNames.has(target.node)) {
|
||||
// Check if they're using an ID instead of name
|
||||
if (nodeIds.has(target.node)) {
|
||||
const correctName = nodeIdToName.get(target.node);
|
||||
errors.push(`Connection target uses node ID '${target.node}' but must use node name '${correctName}' (from ${sourceName}[${outputIndex}][${targetIndex}])`);
|
||||
} else {
|
||||
errors.push(`Connection references non-existent target node: ${target.node} (from ${sourceName}[${outputIndex}][${targetIndex}])`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user