mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-01-30 06:22:04 +00:00
- Add universal expression validator with 100% reliable detection - Implement confidence-based scoring for node-specific recommendations - Add resource locator format detection and validation - Fix pattern matching precision (exact/prefix instead of includes) - Add recursion depth protection (MAX_RECURSION_DEPTH = 100) - Validate resource locator modes (id, url, expression, name, list) - Separate universal rules from node-specific intelligence - Add comprehensive test coverage (94%+ statements) - Prevent common AI agent mistakes with expressions Addresses code review feedback with critical fixes and enhancements. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
148 lines
5.3 KiB
TypeScript
148 lines
5.3 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { ConfidenceScorer } from '../../../src/services/confidence-scorer';
|
|
|
|
describe('ConfidenceScorer', () => {
|
|
describe('scoreResourceLocatorRecommendation', () => {
|
|
it('should give high confidence for exact field matches', () => {
|
|
const score = ConfidenceScorer.scoreResourceLocatorRecommendation(
|
|
'owner',
|
|
'n8n-nodes-base.github',
|
|
'={{ $json.owner }}'
|
|
);
|
|
|
|
expect(score.value).toBeGreaterThanOrEqual(0.5);
|
|
expect(score.factors.find(f => f.name === 'exact-field-match')?.matched).toBe(true);
|
|
});
|
|
|
|
it('should give medium confidence for field pattern matches', () => {
|
|
const score = ConfidenceScorer.scoreResourceLocatorRecommendation(
|
|
'customerId',
|
|
'n8n-nodes-base.customApi',
|
|
'={{ $json.id }}'
|
|
);
|
|
|
|
expect(score.value).toBeGreaterThan(0);
|
|
expect(score.value).toBeLessThan(0.8);
|
|
expect(score.factors.find(f => f.name === 'field-pattern')?.matched).toBe(true);
|
|
});
|
|
|
|
it('should give low confidence for unrelated fields', () => {
|
|
const score = ConfidenceScorer.scoreResourceLocatorRecommendation(
|
|
'message',
|
|
'n8n-nodes-base.emailSend',
|
|
'={{ $json.content }}'
|
|
);
|
|
|
|
expect(score.value).toBeLessThan(0.3);
|
|
});
|
|
|
|
it('should consider value patterns', () => {
|
|
const score = ConfidenceScorer.scoreResourceLocatorRecommendation(
|
|
'target',
|
|
'n8n-nodes-base.httpRequest',
|
|
'={{ $json.userId }}'
|
|
);
|
|
|
|
const valueFactor = score.factors.find(f => f.name === 'value-pattern');
|
|
expect(valueFactor?.matched).toBe(true);
|
|
});
|
|
|
|
it('should consider node category', () => {
|
|
const scoreGitHub = ConfidenceScorer.scoreResourceLocatorRecommendation(
|
|
'field',
|
|
'n8n-nodes-base.github',
|
|
'={{ $json.value }}'
|
|
);
|
|
|
|
const scoreEmail = ConfidenceScorer.scoreResourceLocatorRecommendation(
|
|
'field',
|
|
'n8n-nodes-base.emailSend',
|
|
'={{ $json.value }}'
|
|
);
|
|
|
|
expect(scoreGitHub.value).toBeGreaterThan(scoreEmail.value);
|
|
});
|
|
|
|
it('should handle GitHub repository field with high confidence', () => {
|
|
const score = ConfidenceScorer.scoreResourceLocatorRecommendation(
|
|
'repository',
|
|
'n8n-nodes-base.github',
|
|
'={{ $vars.GITHUB_REPO }}'
|
|
);
|
|
|
|
expect(score.value).toBeGreaterThanOrEqual(0.5);
|
|
expect(ConfidenceScorer.getConfidenceLevel(score.value)).not.toBe('very-low');
|
|
});
|
|
|
|
it('should handle Slack channel field with high confidence', () => {
|
|
const score = ConfidenceScorer.scoreResourceLocatorRecommendation(
|
|
'channel',
|
|
'n8n-nodes-base.slack',
|
|
'={{ $json.channelId }}'
|
|
);
|
|
|
|
expect(score.value).toBeGreaterThanOrEqual(0.5);
|
|
});
|
|
});
|
|
|
|
describe('getConfidenceLevel', () => {
|
|
it('should return correct confidence levels', () => {
|
|
expect(ConfidenceScorer.getConfidenceLevel(0.9)).toBe('high');
|
|
expect(ConfidenceScorer.getConfidenceLevel(0.8)).toBe('high');
|
|
expect(ConfidenceScorer.getConfidenceLevel(0.6)).toBe('medium');
|
|
expect(ConfidenceScorer.getConfidenceLevel(0.5)).toBe('medium');
|
|
expect(ConfidenceScorer.getConfidenceLevel(0.4)).toBe('low');
|
|
expect(ConfidenceScorer.getConfidenceLevel(0.3)).toBe('low');
|
|
expect(ConfidenceScorer.getConfidenceLevel(0.2)).toBe('very-low');
|
|
expect(ConfidenceScorer.getConfidenceLevel(0)).toBe('very-low');
|
|
});
|
|
});
|
|
|
|
describe('shouldApplyRecommendation', () => {
|
|
it('should apply based on threshold', () => {
|
|
// Strict threshold (0.8)
|
|
expect(ConfidenceScorer.shouldApplyRecommendation(0.9, 'strict')).toBe(true);
|
|
expect(ConfidenceScorer.shouldApplyRecommendation(0.7, 'strict')).toBe(false);
|
|
|
|
// Normal threshold (0.5)
|
|
expect(ConfidenceScorer.shouldApplyRecommendation(0.6, 'normal')).toBe(true);
|
|
expect(ConfidenceScorer.shouldApplyRecommendation(0.4, 'normal')).toBe(false);
|
|
|
|
// Relaxed threshold (0.3)
|
|
expect(ConfidenceScorer.shouldApplyRecommendation(0.4, 'relaxed')).toBe(true);
|
|
expect(ConfidenceScorer.shouldApplyRecommendation(0.2, 'relaxed')).toBe(false);
|
|
});
|
|
|
|
it('should use normal threshold by default', () => {
|
|
expect(ConfidenceScorer.shouldApplyRecommendation(0.6)).toBe(true);
|
|
expect(ConfidenceScorer.shouldApplyRecommendation(0.4)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('confidence factors', () => {
|
|
it('should include all expected factors', () => {
|
|
const score = ConfidenceScorer.scoreResourceLocatorRecommendation(
|
|
'testField',
|
|
'n8n-nodes-base.testNode',
|
|
'={{ $json.test }}'
|
|
);
|
|
|
|
expect(score.factors).toHaveLength(4);
|
|
expect(score.factors.map(f => f.name)).toContain('exact-field-match');
|
|
expect(score.factors.map(f => f.name)).toContain('field-pattern');
|
|
expect(score.factors.map(f => f.name)).toContain('value-pattern');
|
|
expect(score.factors.map(f => f.name)).toContain('node-category');
|
|
});
|
|
|
|
it('should have reasonable weights', () => {
|
|
const score = ConfidenceScorer.scoreResourceLocatorRecommendation(
|
|
'testField',
|
|
'n8n-nodes-base.testNode',
|
|
'={{ $json.test }}'
|
|
);
|
|
|
|
const totalWeight = score.factors.reduce((sum, f) => sum + f.weight, 0);
|
|
expect(totalWeight).toBeCloseTo(1.0, 1);
|
|
});
|
|
});
|
|
}); |