mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-08-28 05:25:25 +00:00
150 lines
6.2 KiB
TypeScript
150 lines
6.2 KiB
TypeScript
/**
|
||
* Unit Tests: Impact confidence per relation type (#412)
|
||
*
|
||
* Tests IMPACT_RELATION_CONFIDENCE and confidenceForRelType (tested
|
||
* indirectly) to verify that:
|
||
*
|
||
* 1. Each known relation type maps to the expected confidence floor.
|
||
* 2. Unknown / undefined relation types fall back to 0.5 (conservative).
|
||
* 3. Stored graph confidence is preferred over the type-based floor.
|
||
* 4. Confidence values are in the valid 0–1 range.
|
||
*/
|
||
import { describe, it, expect } from 'vitest';
|
||
import {
|
||
IMPACT_RELATION_CONFIDENCE,
|
||
VALID_RELATION_TYPES,
|
||
} from '../../src/mcp/local/local-backend.js';
|
||
|
||
// ─── IMPACT_RELATION_CONFIDENCE — value assertions ────────────────────────
|
||
|
||
describe('IMPACT_RELATION_CONFIDENCE', () => {
|
||
it('CALLS has confidence 0.9 (direct reference)', () => {
|
||
expect(IMPACT_RELATION_CONFIDENCE['CALLS']).toBe(0.9);
|
||
});
|
||
|
||
it('IMPORTS has confidence 0.9 (direct reference)', () => {
|
||
expect(IMPACT_RELATION_CONFIDENCE['IMPORTS']).toBe(0.9);
|
||
});
|
||
|
||
it('EXTENDS has confidence 0.85 (statically verifiable inheritance)', () => {
|
||
expect(IMPACT_RELATION_CONFIDENCE['EXTENDS']).toBe(0.85);
|
||
});
|
||
|
||
it('IMPLEMENTS has confidence 0.85 (statically verifiable contract)', () => {
|
||
expect(IMPACT_RELATION_CONFIDENCE['IMPLEMENTS']).toBe(0.85);
|
||
});
|
||
|
||
it('METHOD_OVERRIDES has confidence 0.85 (statically verifiable override)', () => {
|
||
expect(IMPACT_RELATION_CONFIDENCE['METHOD_OVERRIDES']).toBe(0.85);
|
||
});
|
||
|
||
it('METHOD_IMPLEMENTS has confidence 0.85 (statically verifiable implementation)', () => {
|
||
expect(IMPACT_RELATION_CONFIDENCE['METHOD_IMPLEMENTS']).toBe(0.85);
|
||
});
|
||
|
||
it('HAS_METHOD has confidence 0.95 (structural containment)', () => {
|
||
expect(IMPACT_RELATION_CONFIDENCE['HAS_METHOD']).toBe(0.95);
|
||
});
|
||
|
||
it('HAS_PROPERTY has confidence 0.95 (structural containment)', () => {
|
||
expect(IMPACT_RELATION_CONFIDENCE['HAS_PROPERTY']).toBe(0.95);
|
||
});
|
||
|
||
it('ACCESSES has confidence 0.8 (may be indirect read/write)', () => {
|
||
expect(IMPACT_RELATION_CONFIDENCE['ACCESSES']).toBe(0.8);
|
||
});
|
||
|
||
it('CONTAINS has confidence 0.95 (folder/file structural containment)', () => {
|
||
expect(IMPACT_RELATION_CONFIDENCE['CONTAINS']).toBe(0.95);
|
||
});
|
||
|
||
it('all defined confidence values are in the valid [0, 1] range', () => {
|
||
for (const [type, confidence] of Object.entries(IMPACT_RELATION_CONFIDENCE)) {
|
||
expect(confidence, `${type} confidence out of range`).toBeGreaterThanOrEqual(0);
|
||
expect(confidence, `${type} confidence out of range`).toBeLessThanOrEqual(1);
|
||
}
|
||
});
|
||
});
|
||
|
||
// ─── confidenceForRelType — fallback semantics ────────────────────────────
|
||
//
|
||
// confidenceForRelType is not exported, so we replicate its logic here to
|
||
// verify the semantics that the production code must uphold.
|
||
|
||
const confidenceForRelType = (relType: string | undefined): number =>
|
||
IMPACT_RELATION_CONFIDENCE[relType ?? ''] ?? 0.5;
|
||
|
||
describe('confidenceForRelType', () => {
|
||
it('returns the correct floor for known types', () => {
|
||
expect(confidenceForRelType('CALLS')).toBe(0.9);
|
||
expect(confidenceForRelType('IMPORTS')).toBe(0.9);
|
||
expect(confidenceForRelType('EXTENDS')).toBe(0.85);
|
||
expect(confidenceForRelType('IMPLEMENTS')).toBe(0.85);
|
||
expect(confidenceForRelType('METHOD_OVERRIDES')).toBe(0.85);
|
||
expect(confidenceForRelType('METHOD_IMPLEMENTS')).toBe(0.85);
|
||
expect(confidenceForRelType('HAS_METHOD')).toBe(0.95);
|
||
expect(confidenceForRelType('HAS_PROPERTY')).toBe(0.95);
|
||
expect(confidenceForRelType('ACCESSES')).toBe(0.8);
|
||
expect(confidenceForRelType('CONTAINS')).toBe(0.95);
|
||
});
|
||
|
||
it('returns 0.5 for unknown relation types', () => {
|
||
expect(confidenceForRelType('UNKNOWN_EDGE')).toBe(0.5);
|
||
expect(confidenceForRelType('SOME_FUTURE_TYPE')).toBe(0.5);
|
||
expect(confidenceForRelType('')).toBe(0.5);
|
||
});
|
||
|
||
it('returns 0.5 for undefined relation type', () => {
|
||
expect(confidenceForRelType(undefined)).toBe(0.5);
|
||
});
|
||
});
|
||
|
||
// ─── Effective confidence selection — stored value wins ───────────────────
|
||
//
|
||
// Verify the priority logic: stored graph confidence beats the type floor.
|
||
|
||
describe('effective confidence selection (stored vs type-floor)', () => {
|
||
const pickConfidence = (storedConfidence: number | undefined, relationType: string): number => {
|
||
return typeof storedConfidence === 'number' && storedConfidence > 0
|
||
? storedConfidence
|
||
: confidenceForRelType(relationType);
|
||
};
|
||
|
||
it('uses stored confidence when it is a positive number', () => {
|
||
expect(pickConfidence(0.95, 'CALLS')).toBe(0.95);
|
||
expect(pickConfidence(0.7, 'EXTENDS')).toBe(0.7);
|
||
expect(pickConfidence(0.3, 'ACCESSES')).toBe(0.3);
|
||
});
|
||
|
||
it('falls back to type floor when stored confidence is undefined', () => {
|
||
expect(pickConfidence(undefined, 'CALLS')).toBe(0.9);
|
||
expect(pickConfidence(undefined, 'EXTENDS')).toBe(0.85);
|
||
expect(pickConfidence(undefined, 'UNKNOWN')).toBe(0.5);
|
||
});
|
||
|
||
it('falls back to type floor when stored confidence is 0 (not a valid confidence)', () => {
|
||
// 0 means "no confidence stored", not "zero confidence"
|
||
expect(pickConfidence(0, 'CALLS')).toBe(0.9);
|
||
expect(pickConfidence(0, 'IMPLEMENTS')).toBe(0.85);
|
||
});
|
||
|
||
it('stored confidence can be lower than the type floor (respects analysis result)', () => {
|
||
// If analysis determined a low-confidence match, honour it
|
||
expect(pickConfidence(0.5, 'HAS_METHOD')).toBe(0.5); // floor is 0.95, stored wins
|
||
});
|
||
});
|
||
|
||
// ─── VALID_RELATION_TYPES consistency ─────────────────────────────────────
|
||
|
||
describe('IMPACT_RELATION_CONFIDENCE vs VALID_RELATION_TYPES', () => {
|
||
it('every key in IMPACT_RELATION_CONFIDENCE except CONTAINS is in VALID_RELATION_TYPES', () => {
|
||
// CONTAINS is a graph-internal structural type, not exposed in impact filters
|
||
const skipInValid = new Set(['CONTAINS']);
|
||
for (const type of Object.keys(IMPACT_RELATION_CONFIDENCE)) {
|
||
if (skipInValid.has(type)) continue;
|
||
expect(VALID_RELATION_TYPES.has(type), `${type} missing from VALID_RELATION_TYPES`).toBe(
|
||
true,
|
||
);
|
||
}
|
||
});
|
||
});
|