fix: correct misleading Code node documentation based on real-world testing
Critical fixes based on Claude Desktop feedback:
1. Fixed crypto documentation: require('crypto') IS available despite editor warnings
- Added clear examples of crypto usage
- Updated validation to guide correct require() usage
2. Clarified $helpers vs standalone functions
- $getWorkflowStaticData() is standalone, NOT $helpers.getWorkflowStaticData()
- Added validation to catch incorrect usage (prevents '$helpers is not defined' errors)
- Enhanced examples showing proper $helpers availability checks
3. Fixed JMESPath numeric literal documentation
- n8n requires backticks around numbers in filters: [?age >= `18`]
- Added multiple examples and validation to detect missing backticks
- Prevents 'JMESPath syntax error' that Claude Desktop encountered
4. Fixed webhook data access gotcha
- Webhook payload is at items[0].json.body, NOT items[0].json
- Added dedicated 'Webhook Data Access' section with clear examples
- Created process_webhook_data task template
- Added validation to detect incorrect webhook data access patterns
All fixes based on production workflows TaNqYoZNNeHC4Hne and JZ9urD7PNClDZ1bm
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
203
scripts/test-code-node-enhancements.ts
Executable file
203
scripts/test-code-node-enhancements.ts
Executable file
@@ -0,0 +1,203 @@
|
||||
#!/usr/bin/env npx tsx
|
||||
|
||||
/**
|
||||
* Test script for Code node enhancements
|
||||
* Tests:
|
||||
* 1. Code node documentation in tools_documentation
|
||||
* 2. Enhanced validation for Code nodes
|
||||
* 3. Code node examples
|
||||
* 4. Code node task templates
|
||||
*/
|
||||
|
||||
import { EnhancedConfigValidator } from '../src/services/enhanced-config-validator.js';
|
||||
import { ExampleGenerator } from '../src/services/example-generator.js';
|
||||
import { TaskTemplates } from '../src/services/task-templates.js';
|
||||
import { getToolDocumentation } from '../src/mcp/tools-documentation.js';
|
||||
|
||||
console.log('🧪 Testing Code Node Enhancements\n');
|
||||
|
||||
// Test 1: Code node documentation
|
||||
console.log('1️⃣ Testing Code Node Documentation');
|
||||
console.log('=====================================');
|
||||
const codeNodeDocs = getToolDocumentation('code_node_guide', 'essentials');
|
||||
console.log('✅ Code node documentation available');
|
||||
console.log('First 500 chars:', codeNodeDocs.substring(0, 500) + '...\n');
|
||||
|
||||
// Test 2: Code node validation
|
||||
console.log('2️⃣ Testing Code Node Validation');
|
||||
console.log('=====================================');
|
||||
|
||||
// Test cases
|
||||
const validationTests = [
|
||||
{
|
||||
name: 'Empty code',
|
||||
config: {
|
||||
language: 'javaScript',
|
||||
jsCode: ''
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'No return statement',
|
||||
config: {
|
||||
language: 'javaScript',
|
||||
jsCode: 'const data = items;'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Invalid return format',
|
||||
config: {
|
||||
language: 'javaScript',
|
||||
jsCode: 'return "hello";'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Valid code',
|
||||
config: {
|
||||
language: 'javaScript',
|
||||
jsCode: 'return [{json: {result: "success"}}];'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Python with external library',
|
||||
config: {
|
||||
language: 'python',
|
||||
pythonCode: 'import pandas as pd\nreturn [{"json": {"result": "fail"}}]'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Code with $json in wrong mode',
|
||||
config: {
|
||||
language: 'javaScript',
|
||||
jsCode: 'const value = $json.field;\nreturn [{json: {value}}];'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Code with security issue',
|
||||
config: {
|
||||
language: 'javaScript',
|
||||
jsCode: 'const result = eval(item.json.code);\nreturn [{json: {result}}];'
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
for (const test of validationTests) {
|
||||
console.log(`\nTest: ${test.name}`);
|
||||
const result = EnhancedConfigValidator.validateWithMode(
|
||||
'nodes-base.code',
|
||||
test.config,
|
||||
[
|
||||
{ name: 'language', type: 'options', options: ['javaScript', 'python'] },
|
||||
{ name: 'jsCode', type: 'string' },
|
||||
{ name: 'pythonCode', type: 'string' },
|
||||
{ name: 'mode', type: 'options', options: ['runOnceForAllItems', 'runOnceForEachItem'] }
|
||||
],
|
||||
'operation',
|
||||
'ai-friendly'
|
||||
);
|
||||
|
||||
console.log(` Valid: ${result.valid}`);
|
||||
if (result.errors.length > 0) {
|
||||
console.log(` Errors: ${result.errors.map(e => e.message).join(', ')}`);
|
||||
}
|
||||
if (result.warnings.length > 0) {
|
||||
console.log(` Warnings: ${result.warnings.map(w => w.message).join(', ')}`);
|
||||
}
|
||||
if (result.suggestions.length > 0) {
|
||||
console.log(` Suggestions: ${result.suggestions.join(', ')}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Test 3: Code node examples
|
||||
console.log('\n\n3️⃣ Testing Code Node Examples');
|
||||
console.log('=====================================');
|
||||
|
||||
const codeExamples = ExampleGenerator.getExamples('nodes-base.code');
|
||||
console.log('Available examples:', Object.keys(codeExamples));
|
||||
console.log('\nMinimal example:');
|
||||
console.log(JSON.stringify(codeExamples.minimal, null, 2));
|
||||
console.log('\nCommon example preview:');
|
||||
console.log(codeExamples.common?.jsCode?.substring(0, 200) + '...');
|
||||
|
||||
// Test 4: Code node task templates
|
||||
console.log('\n\n4️⃣ Testing Code Node Task Templates');
|
||||
console.log('=====================================');
|
||||
|
||||
const codeNodeTasks = [
|
||||
'transform_data',
|
||||
'custom_ai_tool',
|
||||
'aggregate_data',
|
||||
'batch_process_with_api',
|
||||
'error_safe_transform',
|
||||
'async_data_processing',
|
||||
'python_data_analysis'
|
||||
];
|
||||
|
||||
for (const taskName of codeNodeTasks) {
|
||||
const template = TaskTemplates.getTemplate(taskName);
|
||||
if (template) {
|
||||
console.log(`\n✅ ${taskName}:`);
|
||||
console.log(` Description: ${template.description}`);
|
||||
console.log(` Language: ${template.configuration.language || 'javaScript'}`);
|
||||
console.log(` Code preview: ${template.configuration.jsCode?.substring(0, 100) || template.configuration.pythonCode?.substring(0, 100)}...`);
|
||||
} else {
|
||||
console.log(`\n❌ ${taskName}: Template not found`);
|
||||
}
|
||||
}
|
||||
|
||||
// Test 5: Validate a complex Code node configuration
|
||||
console.log('\n\n5️⃣ Testing Complex Code Node Validation');
|
||||
console.log('==========================================');
|
||||
|
||||
const complexCode = {
|
||||
language: 'javaScript',
|
||||
mode: 'runOnceForEachItem',
|
||||
jsCode: `// Complex validation test
|
||||
try {
|
||||
const email = $json.email;
|
||||
const response = await $helpers.httpRequest({
|
||||
method: 'POST',
|
||||
url: 'https://api.example.com/validate',
|
||||
body: { email }
|
||||
});
|
||||
|
||||
return [{
|
||||
json: {
|
||||
...response,
|
||||
validated: true
|
||||
}
|
||||
}];
|
||||
} catch (error) {
|
||||
return [{
|
||||
json: {
|
||||
error: error.message,
|
||||
validated: false
|
||||
}
|
||||
}];
|
||||
}`,
|
||||
onError: 'continueRegularOutput',
|
||||
retryOnFail: true,
|
||||
maxTries: 3
|
||||
};
|
||||
|
||||
const complexResult = EnhancedConfigValidator.validateWithMode(
|
||||
'nodes-base.code',
|
||||
complexCode,
|
||||
[
|
||||
{ name: 'language', type: 'options', options: ['javaScript', 'python'] },
|
||||
{ name: 'jsCode', type: 'string' },
|
||||
{ name: 'mode', type: 'options', options: ['runOnceForAllItems', 'runOnceForEachItem'] },
|
||||
{ name: 'onError', type: 'options' },
|
||||
{ name: 'retryOnFail', type: 'boolean' },
|
||||
{ name: 'maxTries', type: 'number' }
|
||||
],
|
||||
'operation',
|
||||
'strict'
|
||||
);
|
||||
|
||||
console.log('Complex code validation:');
|
||||
console.log(` Valid: ${complexResult.valid}`);
|
||||
console.log(` Errors: ${complexResult.errors.length}`);
|
||||
console.log(` Warnings: ${complexResult.warnings.length}`);
|
||||
console.log(` Suggestions: ${complexResult.suggestions.length}`);
|
||||
|
||||
console.log('\n✅ All Code node enhancement tests completed!');
|
||||
Reference in New Issue
Block a user