fix: Profil-State nach Backend-Load in SDK-Context sync + alle Tests fixen
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Failing after 36s
CI / test-python-backend-compliance (push) Successful in 34s
CI / test-python-document-crawler (push) Successful in 26s
CI / test-python-dsms-gateway (push) Successful in 20s
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Failing after 36s
CI / test-python-backend-compliance (push) Successful in 34s
CI / test-python-document-crawler (push) Successful in 26s
CI / test-python-dsms-gateway (push) Successful in 20s
- Company Profile: setCompanyProfile() und COMPLETE_STEP dispatch nach Backend-Load, damit Sidebar-Checkmarks nach Refresh erhalten bleiben - compliance-scope-engine.test.ts: Property-Namen anpassen (composite_score, risk_score, etc.) - dsfa/types.test.ts: 9 Sections (0-8), 7 required, 2 optional - api-client.test.ts: SDKApiClient-Klasse statt nicht-existierendem Singleton - types.test.ts: use-case-assessment statt use-case-workshop - vitest.config.ts: E2E-Verzeichnis aus Vitest excluden Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import { complianceScopeEngine } from '../compliance-scope-engine'
|
||||
|
||||
// Helper: create an answer object (engine reads answerValue + questionId)
|
||||
function ans(questionId: string, answerValue: unknown) {
|
||||
return { questionId, answerValue } as any
|
||||
// Helper: create an answer object (engine reads value + questionId)
|
||||
function ans(questionId: string, value: unknown) {
|
||||
return { questionId, value } as any
|
||||
}
|
||||
|
||||
// Helper: create a minimal triggered-trigger (engine shape, not types shape)
|
||||
@@ -18,10 +18,10 @@ function trigger(ruleId: string, minimumLevel: string, opts: Record<string, unkn
|
||||
describe('calculateScores', () => {
|
||||
it('returns zero composite for empty answers', () => {
|
||||
const scores = complianceScopeEngine.calculateScores([])
|
||||
expect(scores.composite).toBe(0)
|
||||
expect(scores.risk).toBe(0)
|
||||
expect(scores.complexity).toBe(0)
|
||||
expect(scores.assurance).toBe(0)
|
||||
expect(scores.composite_score).toBe(0)
|
||||
expect(scores.risk_score).toBe(0)
|
||||
expect(scores.complexity_score).toBe(0)
|
||||
expect(scores.assurance_need).toBe(0)
|
||||
})
|
||||
|
||||
it('all-false boolean answers → zero composite', () => {
|
||||
@@ -30,25 +30,25 @@ describe('calculateScores', () => {
|
||||
ans('data_minors', false),
|
||||
ans('proc_ai_usage', false),
|
||||
])
|
||||
expect(scores.composite).toBe(0)
|
||||
expect(scores.composite_score).toBe(0)
|
||||
})
|
||||
|
||||
it('boolean true answer increases risk score', () => {
|
||||
const scoresFalse = complianceScopeEngine.calculateScores([ans('data_art9', false)])
|
||||
const scoresTrue = complianceScopeEngine.calculateScores([ans('data_art9', true)])
|
||||
expect(scoresTrue.risk).toBeGreaterThan(scoresFalse.risk)
|
||||
expect(scoresTrue.risk_score).toBeGreaterThan(scoresFalse.risk_score)
|
||||
})
|
||||
|
||||
it('composite is weighted sum: risk×0.4 + complexity×0.3 + assurance×0.3', () => {
|
||||
const scores = complianceScopeEngine.calculateScores([ans('data_art9', true)])
|
||||
const expected = Math.round((scores.risk * 0.4 + scores.complexity * 0.3 + scores.assurance * 0.3) * 10) / 10
|
||||
expect(scores.composite).toBe(expected)
|
||||
const expected = Math.round((scores.risk_score * 0.4 + scores.complexity_score * 0.3 + scores.assurance_need * 0.3) * 10) / 10
|
||||
expect(scores.composite_score).toBe(expected)
|
||||
})
|
||||
|
||||
it('numeric answer uses logarithmic normalization — higher value → higher score', () => {
|
||||
const scoresLow = complianceScopeEngine.calculateScores([ans('data_volume', 10)])
|
||||
const scoresHigh = complianceScopeEngine.calculateScores([ans('data_volume', 999)])
|
||||
expect(scoresHigh.composite).toBeGreaterThan(scoresLow.composite)
|
||||
expect(scoresHigh.composite_score).toBeGreaterThan(scoresLow.composite_score)
|
||||
})
|
||||
|
||||
it('array answer score proportional to count (max 1.0 at 5+)', () => {
|
||||
@@ -56,13 +56,13 @@ describe('calculateScores', () => {
|
||||
const scores5 = complianceScopeEngine.calculateScores([
|
||||
ans('data_art9', ['gesundheit', 'biometrie', 'genetik', 'politisch', 'religion']),
|
||||
])
|
||||
expect(scores5.composite).toBeGreaterThan(scores1.composite)
|
||||
expect(scores5.composite_score).toBeGreaterThan(scores1.composite_score)
|
||||
})
|
||||
|
||||
it('empty array answer → zero contribution', () => {
|
||||
const scoresEmpty = complianceScopeEngine.calculateScores([ans('data_art9', [])])
|
||||
const scoresNone = complianceScopeEngine.calculateScores([])
|
||||
expect(scoresEmpty.composite).toBe(scoresNone.composite)
|
||||
expect(scoresEmpty.composite_score).toBe(scoresNone.composite_score)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -72,56 +72,56 @@ describe('calculateScores', () => {
|
||||
|
||||
describe('determineLevel', () => {
|
||||
it('composite ≤25 → L1', () => {
|
||||
const level = complianceScopeEngine.determineLevel({ composite: 20 } as any, [])
|
||||
const level = complianceScopeEngine.determineLevel({ composite_score: 20 } as any, [])
|
||||
expect(level).toBe('L1')
|
||||
})
|
||||
|
||||
it('composite exactly 25 → L1', () => {
|
||||
const level = complianceScopeEngine.determineLevel({ composite: 25 } as any, [])
|
||||
const level = complianceScopeEngine.determineLevel({ composite_score: 25 } as any, [])
|
||||
expect(level).toBe('L1')
|
||||
})
|
||||
|
||||
it('composite 26–50 → L2', () => {
|
||||
const level = complianceScopeEngine.determineLevel({ composite: 40 } as any, [])
|
||||
const level = complianceScopeEngine.determineLevel({ composite_score: 40 } as any, [])
|
||||
expect(level).toBe('L2')
|
||||
})
|
||||
|
||||
it('composite exactly 50 → L2', () => {
|
||||
const level = complianceScopeEngine.determineLevel({ composite: 50 } as any, [])
|
||||
const level = complianceScopeEngine.determineLevel({ composite_score: 50 } as any, [])
|
||||
expect(level).toBe('L2')
|
||||
})
|
||||
|
||||
it('composite 51–75 → L3', () => {
|
||||
const level = complianceScopeEngine.determineLevel({ composite: 60 } as any, [])
|
||||
const level = complianceScopeEngine.determineLevel({ composite_score: 60 } as any, [])
|
||||
expect(level).toBe('L3')
|
||||
})
|
||||
|
||||
it('composite >75 → L4', () => {
|
||||
const level = complianceScopeEngine.determineLevel({ composite: 80 } as any, [])
|
||||
const level = complianceScopeEngine.determineLevel({ composite_score: 80 } as any, [])
|
||||
expect(level).toBe('L4')
|
||||
})
|
||||
|
||||
it('hard trigger with minimumLevel L3 overrides score-based L1', () => {
|
||||
const t = trigger('HT-A01', 'L3')
|
||||
const level = complianceScopeEngine.determineLevel({ composite: 10 } as any, [t])
|
||||
const level = complianceScopeEngine.determineLevel({ composite_score: 10 } as any, [t])
|
||||
expect(level).toBe('L3')
|
||||
})
|
||||
|
||||
it('hard trigger with minimumLevel L4 overrides score-based L2', () => {
|
||||
const t = trigger('HT-F01', 'L4')
|
||||
const level = complianceScopeEngine.determineLevel({ composite: 40 } as any, [t])
|
||||
const level = complianceScopeEngine.determineLevel({ composite_score: 40 } as any, [t])
|
||||
expect(level).toBe('L4')
|
||||
})
|
||||
|
||||
it('level = max(score-level, trigger-level) — score wins when higher', () => {
|
||||
const t = trigger('HT-B01', 'L2')
|
||||
// score gives L3, trigger gives L2 → max = L3
|
||||
const level = complianceScopeEngine.determineLevel({ composite: 60 } as any, [t])
|
||||
const level = complianceScopeEngine.determineLevel({ composite_score: 60 } as any, [t])
|
||||
expect(level).toBe('L3')
|
||||
})
|
||||
|
||||
it('no triggers with zero composite → L1', () => {
|
||||
const level = complianceScopeEngine.determineLevel({ composite: 0 } as any, [])
|
||||
const level = complianceScopeEngine.determineLevel({ composite_score: 0 } as any, [])
|
||||
expect(level).toBe('L1')
|
||||
})
|
||||
})
|
||||
@@ -215,7 +215,7 @@ describe('evaluate — integration', () => {
|
||||
|
||||
it('composite score non-negative', () => {
|
||||
const decision = complianceScopeEngine.evaluate([ans('org_employee_count', '50-249')])
|
||||
expect((decision.scores as any).composite).toBeGreaterThanOrEqual(0)
|
||||
expect((decision.scores as any).composite_score).toBeGreaterThanOrEqual(0)
|
||||
})
|
||||
|
||||
it('evaluate returns array types for collections', () => {
|
||||
|
||||
Reference in New Issue
Block a user