/** * Risk Classifier Service Tests */ const { RiskClassifierService } = require('../src/services/riskClassifier'); describe('RiskClassifierService', () => { let service; beforeEach(() => { service = new RiskClassifierService(); }); describe('classify', () => { it('should classify skimmer as red', () => { const detection = { anomalyType: 'skimmer', confidence: 0.95 }; const result = service.classify(detection, 'atm'); expect(result.level).toBe('red'); expect(result.action).toBe('immediate_alert'); }); it('should classify camera blocked as orange', () => { const detection = { anomalyType: 'camera_blocked', confidence: 0.8 }; const result = service.classify(detection, 'atm'); expect(result.level).toBe('orange'); }); it('should escalate high confidence anomalies', () => { const detection = { anomalyType: 'display_changed', confidence: 0.95 }; const result = service.classify(detection, 'atm'); // display_changed is yellow but high confidence should escalate expect(result.level).toBe('orange'); }); it('should de-escalate low confidence anomalies', () => { const detection = { anomalyType: 'pin_pad_modified', confidence: 0.3 }; const result = service.classify(detection, 'atm'); // pin_pad_modified is red but low confidence should de-escalate expect(result.level).toBe('orange'); }); }); describe('aggregate', () => { it('should return green for no classifications', () => { const result = service.aggregate([]); expect(result.level).toBe('green'); }); it('should return highest risk level', () => { const classifications = [ { level: 'green', reason: 'Normal' }, { level: 'yellow', reason: 'Minor' }, { level: 'red', reason: 'Critical' } ]; const result = service.aggregate(classifications); expect(result.level).toBe('red'); }); it('should count by level', () => { const classifications = [ { level: 'yellow', reason: 'Minor 1' }, { level: 'yellow', reason: 'Minor 2' }, { level: 'orange', reason: 'Major' } ]; const result = service.aggregate(classifications); expect(result.counts.yellow).toBe(2); expect(result.counts.orange).toBe(1); }); it('should determine action based on highest risk', () => { const classifications = [ { level: 'yellow', reason: 'Minor' } ]; const result = service.aggregate(classifications); expect(result.action).toBe('verify_maintenance'); }); it('should escalate action for multiple yellow', () => { const classifications = [ { level: 'yellow', reason: 'Minor 1' }, { level: 'yellow', reason: 'Minor 2' }, { level: 'yellow', reason: 'Minor 3' } ]; const result = service.aggregate(classifications); expect(result.action).toBe('scheduled_inspection'); }); }); describe('processObservation', () => { it('should process observation with no anomalies', () => { const observation = { id: 'obs-1' }; const detections = [ { componentType: 'card_reader', confidence: 0.9, isAnomaly: false } ]; const result = service.processObservation(observation, detections, 'atm'); expect(result.level).toBe('green'); }); it('should process observation with anomalies', () => { const observation = { id: 'obs-1' }; const detections = [ { componentType: 'skimmer', confidence: 0.9, isAnomaly: true } ]; const result = service.processObservation(observation, detections, 'atm'); expect(result.level).toBe('red'); expect(result.observationId).toBe('obs-1'); }); }); describe('calculateTrend', () => { it('should detect increasing trend', () => { const history = [ { level: 'green' }, { level: 'yellow' }, { level: 'orange' } ]; const result = service.calculateTrend(history); expect(result.trend).toBe('increasing'); }); it('should detect decreasing trend', () => { const history = [ { level: 'red' }, { level: 'orange' }, { level: 'yellow' } ]; const result = service.calculateTrend(history); expect(result.trend).toBe('decreasing'); }); it('should detect stable trend', () => { const history = [ { level: 'green' }, { level: 'green' }, { level: 'green' } ]; const result = service.calculateTrend(history); expect(result.trend).toBe('stable'); }); it('should return stable for insufficient data', () => { const result = service.calculateTrend([]); expect(result.trend).toBe('stable'); expect(result.confidence).toBe(0); }); }); describe('validateRules', () => { it('should validate correct rules', () => { const rules = { atm: { skimmer: { level: 'red', action: 'immediate_alert' } } }; const result = service.validateRules(rules); expect(result.valid).toBe(true); expect(result.errors).toHaveLength(0); }); it('should detect invalid level', () => { const rules = { atm: { skimmer: { level: 'invalid', action: 'immediate_alert' } } }; const result = service.validateRules(rules); expect(result.valid).toBe(false); expect(result.errors.length).toBeGreaterThan(0); }); it('should detect invalid action', () => { const rules = { atm: { skimmer: { level: 'red', action: 'invalid_action' } } }; const result = service.validateRules(rules); expect(result.valid).toBe(false); }); }); });