6de2455917
- Added GLOBAL_MARKETS_TITLE to all translation files - Updated footer with 12 markets (4 active + 8 upcoming) - Translated market section to: zh-cn, zh-tw, ja, ko, th, vi, id, ms, hi - Built and deployed to production - CloudFront invalidation: I3RTMXVFDJXWLG3SYX208OP1CC
110 lines
4.1 KiB
JavaScript
110 lines
4.1 KiB
JavaScript
/**
|
|
* Object Detection Service Tests
|
|
*/
|
|
|
|
const { ObjectDetectionService } = require('../src/services/objectDetection');
|
|
|
|
describe('ObjectDetectionService', () => {
|
|
let service;
|
|
|
|
beforeEach(() => {
|
|
service = new ObjectDetectionService();
|
|
});
|
|
|
|
describe('detect', () => {
|
|
it('should detect components in ATM image', async () => {
|
|
// Create a valid JPEG buffer
|
|
const sharp = require('sharp');
|
|
const mockImage = await sharp({
|
|
create: { width: 640, height: 480, channels: 3, background: { r: 128, g: 128, b: 128 } }
|
|
}).jpeg().toBuffer();
|
|
const result = await service.detect(mockImage, 'atm');
|
|
|
|
expect(result).toHaveProperty('detections');
|
|
expect(result).toHaveProperty('modelVersion');
|
|
expect(result).toHaveProperty('inferenceTime');
|
|
expect(Array.isArray(result.detections)).toBe(true);
|
|
});
|
|
|
|
it('should return detections with required fields', async () => {
|
|
const sharp = require('sharp');
|
|
const mockImage = await sharp({
|
|
create: { width: 640, height: 480, channels: 3, background: { r: 128, g: 128, b: 128 } }
|
|
}).jpeg().toBuffer();
|
|
const result = await service.detect(mockImage, 'atm');
|
|
|
|
if (result.detections.length > 0) {
|
|
const detection = result.detections[0];
|
|
expect(detection).toHaveProperty('componentType');
|
|
expect(detection).toHaveProperty('componentName');
|
|
expect(detection).toHaveProperty('confidence');
|
|
expect(detection).toHaveProperty('boundingBox');
|
|
expect(detection.confidence).toBeGreaterThan(0);
|
|
expect(detection.confidence).toBeLessThanOrEqual(1);
|
|
}
|
|
});
|
|
|
|
it('should handle unknown object type', async () => {
|
|
const sharp = require('sharp');
|
|
const mockImage = await sharp({
|
|
create: { width: 640, height: 480, channels: 3, background: { r: 128, g: 128, b: 128 } }
|
|
}).jpeg().toBuffer();
|
|
const result = await service.detect(mockImage, 'unknown_type');
|
|
|
|
expect(result.detections).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe('detectAnomalies', () => {
|
|
it('should detect new components', async () => {
|
|
const current = [
|
|
{ componentType: 'card_reader', confidence: 0.9, boundingBox: { x: 0.1, y: 0.1, width: 0.2, height: 0.2 } },
|
|
{ componentType: 'skimmer', confidence: 0.8, boundingBox: { x: 0.1, y: 0.1, width: 0.2, height: 0.2 } }
|
|
];
|
|
|
|
const reference = [
|
|
{ componentType: 'card_reader', confidence: 0.9, boundingBox: { x: 0.1, y: 0.1, width: 0.2, height: 0.2 } }
|
|
];
|
|
|
|
const anomalies = await service.detectAnomalies(current, reference, 'atm');
|
|
|
|
expect(anomalies.length).toBeGreaterThan(0);
|
|
expect(anomalies[0].type).toBe('new_object');
|
|
});
|
|
|
|
it('should detect missing components', async () => {
|
|
const current = [
|
|
{ componentType: 'card_reader', confidence: 0.9, boundingBox: { x: 0.1, y: 0.1, width: 0.2, height: 0.2 } }
|
|
];
|
|
|
|
const reference = [
|
|
{ componentType: 'card_reader', confidence: 0.9, boundingBox: { x: 0.1, y: 0.1, width: 0.2, height: 0.2 } },
|
|
{ componentType: 'camera', confidence: 0.9, boundingBox: { x: 0.5, y: 0.5, width: 0.1, height: 0.1 } }
|
|
];
|
|
|
|
const anomalies = await service.detectAnomalies(current, reference, 'atm');
|
|
|
|
const missing = anomalies.find(a => a.type === 'missing_component');
|
|
expect(missing).toBeDefined();
|
|
expect(missing.component).toBe('camera');
|
|
});
|
|
});
|
|
|
|
describe('applyNMS', () => {
|
|
it('should remove overlapping detections', () => {
|
|
const detections = [
|
|
{ componentType: 'card_reader', confidence: 0.9, boundingBox: { x: 0.1, y: 0.1, width: 0.2, height: 0.2 } },
|
|
{ componentType: 'card_reader', confidence: 0.7, boundingBox: { x: 0.12, y: 0.12, width: 0.18, height: 0.18 } },
|
|
{ componentType: 'pin_pad', confidence: 0.8, boundingBox: { x: 0.5, y: 0.5, width: 0.2, height: 0.2 } }
|
|
];
|
|
|
|
const result = service.applyNMS(detections, 0.5);
|
|
|
|
// Should keep highest confidence card_reader and pin_pad
|
|
expect(result.length).toBe(2);
|
|
expect(result[0].componentType).toBe('card_reader');
|
|
expect(result[0].confidence).toBe(0.9);
|
|
});
|
|
});
|
|
});
|