GitNexus/gitnexus/test/unit/analysis-features.test.ts
MyShining 1147646518
feat(spring): model AOP transactions, caching, and security (#2783)
* feat(spring): model AOP advice and proxy behavior

* fix(spring): address AOP review findings

---------

Co-authored-by: Shining <xuenning@qiyi.com>
2026-08-01 17:22:12 +01:00

112 lines
3.9 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import {
CLASS_FRAMEWORK_ANNOTATIONS_FEATURE,
findAnalysisFeatureMismatches,
resolveAnalysisFeatureVersions,
type AnalysisFeatureDescriptor,
} from '../../src/core/analysis-features.js';
import {
SPRING_AOP_FEATURE,
SPRING_BEAN_INVENTORY_FEATURE,
SPRING_CONDITIONALS_FEATURE,
} from '../../src/core/ingestion/frameworks/spring/analysis-features.js';
import { SPRING_CONFIG_BINDINGS_FEATURE } from '../../src/core/ingestion/languages/java/analysis-features.js';
const FEATURES = [
CLASS_FRAMEWORK_ANNOTATIONS_FEATURE,
SPRING_AOP_FEATURE,
SPRING_BEAN_INVENTORY_FEATURE,
SPRING_CONDITIONALS_FEATURE,
SPRING_CONFIG_BINDINGS_FEATURE,
] as const;
describe('analysis feature versions', () => {
it('separates the global Class schema capability from JVM-only Bean evidence', () => {
expect(resolveAnalysisFeatureVersions(FEATURES, ['src/app.ts'])).toEqual({
'graph.class-framework-annotations': 1,
});
expect(resolveAnalysisFeatureVersions(FEATURES, ['src/App.java'])).toEqual({
'graph.class-framework-annotations': 1,
'spring.aop-advice': 1,
'spring.bean-inventory': 2,
'spring.conditionals-auto-configuration': 1,
'spring.config-bindings': 1,
});
expect(resolveAnalysisFeatureVersions(FEATURES, ['BUILD.GRADLE.KTS'])).toEqual({
'graph.class-framework-annotations': 1,
'spring.aop-advice': 1,
'spring.bean-inventory': 2,
'spring.conditionals-auto-configuration': 1,
});
expect(
resolveAnalysisFeatureVersions(FEATURES, [
'src/main/resources/application-local.yml',
'README.md',
]),
).toEqual({
'graph.class-framework-annotations': 1,
'spring.config-bindings': 1,
});
expect(
resolveAnalysisFeatureVersions(FEATURES, [
'src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports',
]),
).toEqual({
'graph.class-framework-annotations': 1,
'spring.conditionals-auto-configuration': 1,
});
});
it('requires an exact, well-formed feature set', () => {
const expected = {
'graph.class-framework-annotations': 1,
'spring.bean-inventory': 2,
};
expect(findAnalysisFeatureMismatches(expected, expected)).toEqual([]);
expect(findAnalysisFeatureMismatches(undefined, expected)).toEqual([
'missing:graph.class-framework-annotations',
'missing:spring.bean-inventory',
]);
expect(
findAnalysisFeatureMismatches(
{ 'graph.class-framework-annotations': 1, 'spring.bean-inventory': 1 },
expected,
),
).toEqual(['version:spring.bean-inventory']);
expect(findAnalysisFeatureMismatches({ feature: 1 }, { feature: 2 })).toEqual([
'version:feature',
]);
expect(
findAnalysisFeatureMismatches({ ...expected, 'spring.future-feature': 1 }, expected),
).toEqual(['unexpected:spring.future-feature']);
expect(findAnalysisFeatureMismatches([], expected)).toEqual(['invalid:analysisFeatures']);
expect(findAnalysisFeatureMismatches({ ...expected, toString: 1 }, expected)).toEqual([
'unexpected:toString',
]);
});
it('rejects invalid or duplicate descriptors', () => {
const invalid: AnalysisFeatureDescriptor = {
id: 'invalid',
version: 0,
appliesTo: () => true,
};
expect(() => resolveAnalysisFeatureVersions([invalid], [])).toThrow('invalid version');
expect(() =>
resolveAnalysisFeatureVersions(
[CLASS_FRAMEWORK_ANNOTATIONS_FEATURE, CLASS_FRAMEWORK_ANNOTATIONS_FEATURE],
[],
),
).toThrow('Duplicate analysis feature descriptor');
expect(() =>
resolveAnalysisFeatureVersions(
[
CLASS_FRAMEWORK_ANNOTATIONS_FEATURE,
{ ...CLASS_FRAMEWORK_ANNOTATIONS_FEATURE, appliesTo: () => false },
],
[],
),
).toThrow('Duplicate analysis feature descriptor');
});
});