diff --git a/tests/unit/mappers/docs-mapper.test.ts b/tests/unit/mappers/docs-mapper.test.ts index b560dbf..85eb4b9 100644 --- a/tests/unit/mappers/docs-mapper.test.ts +++ b/tests/unit/mappers/docs-mapper.test.ts @@ -318,17 +318,18 @@ Use this node when you need to process large datasets in smaller chunks. const result = await docsMapper.fetchDocumentation('splitInBatches'); - expect(result).toContain('CRITICAL OUTPUT CONNECTION INFORMATION'); - expect(result).toContain('⚠️ OUTPUT INDICES ARE COUNTERINTUITIVE ⚠️'); - expect(result).toContain('Output 0 (index 0) = "done"'); - expect(result).toContain('Output 1 (index 1) = "loop"'); - expect(result).toContain('Correct Connection Pattern:'); - expect(result).toContain('Common Mistake:'); - expect(result).toContain('AI assistants often connect these backwards'); + expect(result).not.toBeNull(); + expect(result!).toContain('CRITICAL OUTPUT CONNECTION INFORMATION'); + expect(result!).toContain('⚠️ OUTPUT INDICES ARE COUNTERINTUITIVE ⚠️'); + expect(result!).toContain('Output 0 (index 0) = "done"'); + expect(result!).toContain('Output 1 (index 1) = "loop"'); + expect(result!).toContain('Correct Connection Pattern:'); + expect(result!).toContain('Common Mistake:'); + expect(result!).toContain('AI assistants often connect these backwards'); // Should insert before "When to use" section - const insertionIndex = result.indexOf('## When to use'); - const guidanceIndex = result.indexOf('CRITICAL OUTPUT CONNECTION INFORMATION'); + const insertionIndex = result!.indexOf('## When to use'); + const guidanceIndex = result!.indexOf('CRITICAL OUTPUT CONNECTION INFORMATION'); expect(guidanceIndex).toBeLessThan(insertionIndex); expect(guidanceIndex).toBeGreaterThan(0); }); @@ -347,10 +348,11 @@ This node splits data into batches. const result = await docsMapper.fetchDocumentation('splitInBatches'); - expect(result).toContain('CRITICAL OUTPUT CONNECTION INFORMATION'); + expect(result).not.toBeNull(); + expect(result!).toContain('CRITICAL OUTPUT CONNECTION INFORMATION'); // Should be inserted at the beginning since no "When to use" section - expect(result.indexOf('CRITICAL OUTPUT CONNECTION INFORMATION')).toBeLessThan( - result.indexOf('# Split In Batches Node') + expect(result!.indexOf('CRITICAL OUTPUT CONNECTION INFORMATION')).toBeLessThan( + result!.indexOf('# Split In Batches Node') ); }); @@ -420,15 +422,16 @@ Configure your conditions here. const result = await docsMapper.fetchDocumentation('n8n-nodes-base.if'); - expect(result).toContain('Output Connection Information'); - expect(result).toContain('Output 0 (index 0) = "true"'); - expect(result).toContain('Output 1 (index 1) = "false"'); - expect(result).toContain('Items that match the condition'); - expect(result).toContain('Items that do not match the condition'); + expect(result).not.toBeNull(); + expect(result!).toContain('Output Connection Information'); + expect(result!).toContain('Output 0 (index 0) = "true"'); + expect(result!).toContain('Output 1 (index 1) = "false"'); + expect(result!).toContain('Items that match the condition'); + expect(result!).toContain('Items that do not match the condition'); // Should insert before "Node parameters" section - const parametersIndex = result.indexOf('## Node parameters'); - const outputInfoIndex = result.indexOf('Output Connection Information'); + const parametersIndex = result!.indexOf('## Node parameters'); + const outputInfoIndex = result!.indexOf('Output Connection Information'); expect(outputInfoIndex).toBeLessThan(parametersIndex); expect(outputInfoIndex).toBeGreaterThan(0); }); @@ -483,10 +486,11 @@ Use this node to route data. const result = await docsMapper.fetchDocumentation('splitInBatches'); - expect(result).toContain('CRITICAL OUTPUT CONNECTION INFORMATION'); + expect(result).not.toBeNull(); + expect(result!).toContain('CRITICAL OUTPUT CONNECTION INFORMATION'); // Should be prepended when no insertion point found (but there's a newline before original content) - const guidanceIndex = result.indexOf('CRITICAL OUTPUT CONNECTION INFORMATION'); - expect(guidanceIndex).toBeLessThan(result.indexOf('Simple content')); + const guidanceIndex = result!.indexOf('CRITICAL OUTPUT CONNECTION INFORMATION'); + expect(guidanceIndex).toBeLessThan(result!.indexOf('Simple content')); expect(guidanceIndex).toBeLessThanOrEqual(5); // Allow for some whitespace }); @@ -496,8 +500,9 @@ Use this node to route data. const result = await docsMapper.fetchDocumentation('splitInBatches'); - expect(result).toContain('CRITICAL OUTPUT CONNECTION INFORMATION'); - expect(result.length).toBeGreaterThan(0); + expect(result).not.toBeNull(); + expect(result!).toContain('CRITICAL OUTPUT CONNECTION INFORMATION'); + expect(result!.length).toBeGreaterThan(0); }); it('should handle content with multiple "When to use" sections', async () => { @@ -515,10 +520,11 @@ Detailed usage. const result = await docsMapper.fetchDocumentation('splitInBatches'); - expect(result).toContain('CRITICAL OUTPUT CONNECTION INFORMATION'); + expect(result).not.toBeNull(); + expect(result!).toContain('CRITICAL OUTPUT CONNECTION INFORMATION'); // Should insert before first occurrence - const firstWhenToUse = result.indexOf('## When to use (overview)'); - const guidanceIndex = result.indexOf('CRITICAL OUTPUT CONNECTION INFORMATION'); + const firstWhenToUse = result!.indexOf('## When to use (overview)'); + const guidanceIndex = result!.indexOf('CRITICAL OUTPUT CONNECTION INFORMATION'); expect(guidanceIndex).toBeLessThan(firstWhenToUse); }); @@ -538,7 +544,8 @@ Content here. const result = await docsMapper.fetchDocumentation('splitInBatches'); // Should still add enhancement (method doesn't check for existing enhancements) - const criticalSections = (result.match(/CRITICAL OUTPUT CONNECTION INFORMATION/g) || []).length; + expect(result).not.toBeNull(); + const criticalSections = (result!.match(/CRITICAL OUTPUT CONNECTION INFORMATION/g) || []).length; expect(criticalSections).toBe(2); // Original + new enhancement }); @@ -548,8 +555,9 @@ Content here. const result = await docsMapper.fetchDocumentation('splitInBatches'); - expect(result).toContain('CRITICAL OUTPUT CONNECTION INFORMATION'); - expect(result.length).toBeGreaterThan(largeContent.length); + expect(result).not.toBeNull(); + expect(result!).toContain('CRITICAL OUTPUT CONNECTION INFORMATION'); + expect(result!.length).toBeGreaterThan(largeContent.length); }); }); diff --git a/tests/unit/parsers/node-parser-outputs.test.ts b/tests/unit/parsers/node-parser-outputs.test.ts index 89d5195..800d4fa 100644 --- a/tests/unit/parsers/node-parser-outputs.test.ts +++ b/tests/unit/parsers/node-parser-outputs.test.ts @@ -306,10 +306,12 @@ describe('NodeParser - Output Extraction', () => { expect(result.outputNames).toEqual(['done', 'loop']); // Verify the counterintuitive order: done=0, loop=1 - expect(result.outputs[0].displayName).toBe('Done'); - expect(result.outputs[1].displayName).toBe('Loop'); - expect(result.outputNames[0]).toBe('done'); - expect(result.outputNames[1]).toBe('loop'); + expect(result.outputs).toBeDefined(); + expect(result.outputNames).toBeDefined(); + expect(result.outputs![0].displayName).toBe('Done'); + expect(result.outputs![1].displayName).toBe('Loop'); + expect(result.outputNames![0]).toBe('done'); + expect(result.outputNames![1]).toBe('loop'); }); it('should handle Switch node with multiple outputs', () => { @@ -406,8 +408,9 @@ describe('NodeParser - Output Extraction', () => { const result = parser.parse(NodeClass, 'n8n-nodes-base'); expect(result.outputs).toHaveLength(2); - expect(result.outputs[0].displayName).toBe('Done'); - expect(result.outputs[1].displayName).toBe('Loop'); + expect(result.outputs).toBeDefined(); + expect(result.outputs![0].displayName).toBe('Done'); + expect(result.outputs![1].displayName).toBe('Loop'); expect(result.outputNames).toEqual(['done', 'loop']); }); @@ -442,8 +445,9 @@ describe('NodeParser - Output Extraction', () => { const result = parser.parse(NodeClass, 'n8n-nodes-base'); expect(result.outputs).toHaveLength(2); - expect(result.outputs[0].displayName).toBe('True'); - expect(result.outputs[1].displayName).toBe('False'); + expect(result.outputs).toBeDefined(); + expect(result.outputs![0].displayName).toBe('True'); + expect(result.outputs![1].displayName).toBe('False'); expect(result.outputNames).toEqual(['true', 'false']); }); diff --git a/tests/unit/services/loop-output-edge-cases.test.ts b/tests/unit/services/loop-output-edge-cases.test.ts index 93507ac..85916cc 100644 --- a/tests/unit/services/loop-output-edge-cases.test.ts +++ b/tests/unit/services/loop-output-edge-cases.test.ts @@ -82,7 +82,7 @@ describe('Loop Output Fix - Edge Cases', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should not crash or produce output-related errors expect(result).toBeDefined(); @@ -113,7 +113,7 @@ describe('Loop Output Fix - Edge Cases', () => { connections: {} }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); expect(result).toBeDefined(); expect(result.valid).toBeTruthy(); // Empty workflow with webhook should be valid @@ -147,7 +147,7 @@ describe('Loop Output Fix - Edge Cases', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should warn about self-reference but not crash const selfRefWarnings = result.warnings.filter(w => @@ -188,7 +188,7 @@ describe('Loop Output Fix - Edge Cases', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); const negativeIndexErrors = result.errors.filter(e => e.message?.includes('Invalid connection index -1') @@ -234,7 +234,7 @@ describe('Loop Output Fix - Edge Cases', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should validate without crashing (n8n allows large indices) expect(result).toBeDefined(); @@ -266,7 +266,7 @@ describe('Loop Output Fix - Edge Cases', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should handle gracefully without crashing expect(result).toBeDefined(); @@ -306,7 +306,7 @@ describe('Loop Output Fix - Edge Cases', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should handle malformed connections but report errors expect(result).toBeDefined(); @@ -366,7 +366,7 @@ describe('Loop Output Fix - Edge Cases', () => { connections }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should warn about missing loop back because depth limit prevents detection const loopBackWarnings = result.warnings.filter(w => @@ -423,7 +423,7 @@ describe('Loop Output Fix - Edge Cases', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should complete without hanging and warn about missing loop back expect(result).toBeDefined(); @@ -469,7 +469,7 @@ describe('Loop Output Fix - Edge Cases', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should warn about missing loop back and self-reference const loopBackWarnings = result.warnings.filter(w => @@ -526,7 +526,7 @@ describe('Loop Output Fix - Edge Cases', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should handle without performance issues expect(result).toBeDefined(); @@ -589,7 +589,7 @@ describe('Loop Output Fix - Edge Cases', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should validate all connection types expect(result).toBeDefined(); @@ -615,7 +615,7 @@ describe('Loop Output Fix - Edge Cases', () => { connections: {} }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should not produce SplitInBatches-specific warnings for isolated node const splitWarnings = result.warnings.filter(w => @@ -657,7 +657,7 @@ describe('Loop Output Fix - Edge Cases', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should NOT warn about empty loop output (it's only a problem if loop connects to something but doesn't loop back) // An empty loop output is valid - it just means no looping occurs @@ -703,7 +703,7 @@ describe('Loop Output Fix - Edge Cases', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Both outputs go to same node which loops back - should be valid // No warnings about loop back since it does connect back @@ -749,7 +749,7 @@ describe('Loop Output Fix - Edge Cases', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should error about reversed outputs since function node on done output connects back const reversedErrors = result.errors.filter(e => @@ -776,7 +776,7 @@ describe('Loop Output Fix - Edge Cases', () => { connections: {} }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should report unknown node type error const unknownNodeErrors = result.errors.filter(e => @@ -817,7 +817,7 @@ describe('Loop Output Fix - Edge Cases', () => { }; const startTime = Date.now(); - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); const duration = Date.now() - startTime; // Should complete within reasonable time (< 5 seconds) @@ -855,7 +855,7 @@ describe('Loop Output Fix - Edge Cases', () => { connections }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should validate all nodes without performance issues expect(result).toBeDefined(); diff --git a/tests/unit/services/workflow-validator-loops-simple.test.ts b/tests/unit/services/workflow-validator-loops-simple.test.ts index 1c16e4f..a9c4339 100644 --- a/tests/unit/services/workflow-validator-loops-simple.test.ts +++ b/tests/unit/services/workflow-validator-loops-simple.test.ts @@ -64,7 +64,7 @@ describe('WorkflowValidator - SplitInBatches Validation (Simplified)', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should complete validation without crashing expect(result).toBeDefined(); @@ -114,7 +114,7 @@ describe('WorkflowValidator - SplitInBatches Validation (Simplified)', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should identify potential processing nodes expect(result).toBeDefined(); @@ -163,7 +163,7 @@ describe('WorkflowValidator - SplitInBatches Validation (Simplified)', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should not warn about final nodes on done output expect(result).toBeDefined(); @@ -205,7 +205,7 @@ describe('WorkflowValidator - SplitInBatches Validation (Simplified)', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); const negativeIndexErrors = result.errors.filter(e => e.message?.includes('Invalid connection index -1') @@ -239,7 +239,7 @@ describe('WorkflowValidator - SplitInBatches Validation (Simplified)', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); const missingNodeErrors = result.errors.filter(e => e.message?.includes('non-existent node') @@ -276,7 +276,7 @@ describe('WorkflowValidator - SplitInBatches Validation (Simplified)', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should not warn about self-reference for SplitInBatches const selfRefWarnings = result.warnings.filter(w => @@ -311,7 +311,7 @@ describe('WorkflowValidator - SplitInBatches Validation (Simplified)', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should warn about self-reference for non-loop nodes const selfRefWarnings = result.warnings.filter(w => @@ -368,7 +368,7 @@ describe('WorkflowValidator - SplitInBatches Validation (Simplified)', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should validate without major errors expect(result).toBeDefined(); @@ -399,7 +399,7 @@ describe('WorkflowValidator - SplitInBatches Validation (Simplified)', () => { connections: {} }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should handle gracefully without crashing expect(result).toBeDefined(); @@ -422,7 +422,7 @@ describe('WorkflowValidator - SplitInBatches Validation (Simplified)', () => { connections: {} }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should report unknown node error const unknownErrors = result.errors.filter(e => diff --git a/tests/unit/services/workflow-validator-loops.test.ts b/tests/unit/services/workflow-validator-loops.test.ts index 920e29b..fdeb18c 100644 --- a/tests/unit/services/workflow-validator-loops.test.ts +++ b/tests/unit/services/workflow-validator-loops.test.ts @@ -98,7 +98,7 @@ describe('WorkflowValidator - Loop Node Validation', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // The validator should detect the processing node name/type pattern and loop back const reversedErrors = result.errors.filter(e => @@ -125,7 +125,7 @@ describe('WorkflowValidator - Loop Node Validation', () => { // No loop back from Process Item }); - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); expect(result.warnings).toContainEqual( expect.objectContaining({ @@ -153,7 +153,7 @@ describe('WorkflowValidator - Loop Node Validation', () => { } }); - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); expect(result.warnings).toContainEqual( expect.objectContaining({ @@ -182,7 +182,7 @@ describe('WorkflowValidator - Loop Node Validation', () => { // Process Item doesn't connect back to Split In Batches }); - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); expect(result.warnings).toContainEqual( expect.objectContaining({ @@ -241,7 +241,7 @@ describe('WorkflowValidator - Loop Node Validation', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should not have SplitInBatches-specific errors or warnings const splitErrors = result.errors.filter(e => @@ -317,7 +317,7 @@ describe('WorkflowValidator - Loop Node Validation', () => { } }; - const result = await validator.validateWorkflow(complexWorkflow); + const result = await validator.validateWorkflow(complexWorkflow as any); // Should accept this correct structure without warnings const loopWarnings = result.warnings.filter(w => @@ -369,7 +369,7 @@ describe('WorkflowValidator - Loop Node Validation', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); const hasProcessingWarning = result.warnings.some(w => w.message?.includes('appears to be a processing node') @@ -409,7 +409,7 @@ describe('WorkflowValidator - Loop Node Validation', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should not warn about missing loop back since it exists const missingLoopBackWarnings = result.warnings.filter(w => @@ -454,7 +454,7 @@ describe('WorkflowValidator - Loop Node Validation', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should not warn about missing loop back since indirect loop exists const missingLoopBackWarnings = result.warnings.filter(w => @@ -507,7 +507,7 @@ describe('WorkflowValidator - Loop Node Validation', () => { connections }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should warn about missing loop back because depth limit prevents detection const missingLoopBackWarnings = result.warnings.filter(w => @@ -546,7 +546,7 @@ describe('WorkflowValidator - Loop Node Validation', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should complete without hanging and warn about missing loop back const missingLoopBackWarnings = result.warnings.filter(w => @@ -578,7 +578,7 @@ describe('WorkflowValidator - Loop Node Validation', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should not warn about self-reference for SplitInBatches const selfReferenceWarnings = result.warnings.filter(w => @@ -607,7 +607,7 @@ describe('WorkflowValidator - Loop Node Validation', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should warn about self-reference for non-loop nodes const selfReferenceWarnings = result.warnings.filter(w => @@ -639,7 +639,7 @@ describe('WorkflowValidator - Loop Node Validation', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should have connection error for non-existent node const connectionErrors = result.errors.filter(e => @@ -669,7 +669,7 @@ describe('WorkflowValidator - Loop Node Validation', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should not crash and should not have SplitInBatches-specific errors expect(result).toBeDefined(); @@ -696,7 +696,7 @@ describe('WorkflowValidator - Loop Node Validation', () => { } }; - const result = await validator.validateWorkflow(workflow); + const result = await validator.validateWorkflow(workflow as any); // Should handle gracefully without crashing expect(result).toBeDefined();