mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-04-01 07:03:08 +00:00
fix: validation bugs — If/Switch version check, Set false positive, bare expressions (#675, #676, #677) (#678)
- #675: Wire `validateConditionNodeStructure` into `WorkflowValidator` with version-conditional checks (If v2.2+ requires options, v2.0-2.1 validates operators, v1.x skipped; Switch v3.2+ requires options) - #676: Fix `validateSet` to check `assignments.assignments` (v3+) alongside `config.values` (v1/v2), eliminating false positive warnings - #677: Add anchored heuristic pre-pass in `ExpressionValidator` detecting bare `$json`, `$node`, `$input`, `$execution`, `$workflow`, `$prevNode`, `$env`, `$now`, `$today`, `$itemIndex`, `$runIndex` references missing `={{ }}` 25 new tests across 3 test files. Conceived by Romuald Członkowski - https://www.aiadvisors.pl/en Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
committed by
GitHub
parent
6e4a9d520d
commit
20ebfbb0fc
@@ -105,6 +105,78 @@ describe('ExpressionValidator', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('bare expression detection', () => {
|
||||
it('should warn on bare $json.name', () => {
|
||||
const params = { value: '$json.name' };
|
||||
const result = ExpressionValidator.validateNodeExpressions(params, defaultContext);
|
||||
expect(result.warnings.some(w => w.includes('unwrapped expression'))).toBe(true);
|
||||
});
|
||||
|
||||
it('should warn on bare $node["Webhook"].json', () => {
|
||||
const params = { value: '$node["Webhook"].json' };
|
||||
const result = ExpressionValidator.validateNodeExpressions(params, defaultContext);
|
||||
expect(result.warnings.some(w => w.includes('unwrapped expression'))).toBe(true);
|
||||
});
|
||||
|
||||
it('should warn on bare $now', () => {
|
||||
const params = { value: '$now' };
|
||||
const result = ExpressionValidator.validateNodeExpressions(params, defaultContext);
|
||||
expect(result.warnings.some(w => w.includes('unwrapped expression'))).toBe(true);
|
||||
});
|
||||
|
||||
it('should warn on bare $execution.id', () => {
|
||||
const params = { value: '$execution.id' };
|
||||
const result = ExpressionValidator.validateNodeExpressions(params, defaultContext);
|
||||
expect(result.warnings.some(w => w.includes('unwrapped expression'))).toBe(true);
|
||||
});
|
||||
|
||||
it('should warn on bare $env.API_KEY', () => {
|
||||
const params = { value: '$env.API_KEY' };
|
||||
const result = ExpressionValidator.validateNodeExpressions(params, defaultContext);
|
||||
expect(result.warnings.some(w => w.includes('unwrapped expression'))).toBe(true);
|
||||
});
|
||||
|
||||
it('should warn on bare $input.item.json.field', () => {
|
||||
const params = { value: '$input.item.json.field' };
|
||||
const result = ExpressionValidator.validateNodeExpressions(params, defaultContext);
|
||||
expect(result.warnings.some(w => w.includes('unwrapped expression'))).toBe(true);
|
||||
});
|
||||
|
||||
it('should NOT warn on properly wrapped ={{ $json.name }}', () => {
|
||||
const params = { value: '={{ $json.name }}' };
|
||||
const result = ExpressionValidator.validateNodeExpressions(params, defaultContext);
|
||||
expect(result.warnings.some(w => w.includes('unwrapped expression'))).toBe(false);
|
||||
});
|
||||
|
||||
it('should NOT warn on properly wrapped {{ $json.name }}', () => {
|
||||
const params = { value: '{{ $json.name }}' };
|
||||
const result = ExpressionValidator.validateNodeExpressions(params, defaultContext);
|
||||
expect(result.warnings.some(w => w.includes('unwrapped expression'))).toBe(false);
|
||||
});
|
||||
|
||||
it('should NOT warn when $json appears mid-string', () => {
|
||||
const params = { value: 'The $json data is ready' };
|
||||
const result = ExpressionValidator.validateNodeExpressions(params, defaultContext);
|
||||
expect(result.warnings.some(w => w.includes('unwrapped expression'))).toBe(false);
|
||||
});
|
||||
|
||||
it('should NOT warn on plain text', () => {
|
||||
const params = { value: 'Hello World' };
|
||||
const result = ExpressionValidator.validateNodeExpressions(params, defaultContext);
|
||||
expect(result.warnings.some(w => w.includes('unwrapped expression'))).toBe(false);
|
||||
});
|
||||
|
||||
it('should detect bare expression in nested structure', () => {
|
||||
const params = {
|
||||
assignments: {
|
||||
assignments: [{ value: '$json.name' }]
|
||||
}
|
||||
};
|
||||
const result = ExpressionValidator.validateNodeExpressions(params, defaultContext);
|
||||
expect(result.warnings.some(w => w.includes('unwrapped expression'))).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('edge cases', () => {
|
||||
it('should handle empty expressions', () => {
|
||||
const result = ExpressionValidator.validateExpression('{{ }}', defaultContext);
|
||||
|
||||
Reference in New Issue
Block a user