import 'package:flutter_test/flutter_test.dart'; import 'package:tactical_app/models/angle_unit.dart'; import 'package:tactical_app/services/camera_sensor_calibration_service.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); group('CameraSensorCalibrationService Tests', () { test('Standard target library contains realistic heights', () { final targets = CameraSensorCalibrationService.standardTargets; expect(targets.isNotEmpty, isTrue); final infantry = targets.firstWhere((t) => t.id == 'infantry'); expect(infantry.heightMeters, equals(1.75)); final minaretShort = targets.firstWhere((t) => t.id == 'minaret_neighborhood'); expect(minaretShort.heightMeters, equals(16.0)); final minaretGrand = targets.firstWhere((t) => t.id == 'minaret_grand'); expect(minaretGrand.heightMeters, equals(24.0)); }); test('Stadiametric rangefinding calculation at 1.0x zoom', () { // Tank (2.7m height), 100 pixels on 1000px screen height final distance = CameraSensorCalibrationService.calculateStadiametricDistance( targetRealHeightMeters: 2.70, reticulePixelHeight: 100.0, screenHeightPixels: 1000.0, zoomMultiplier: 1.0, ); // Distance should be positive and physically proportional expect(distance, greaterThan(20.0)); expect(distance, lessThan(100.0)); }); test('Zoom multiplier scales distance proportionally', () { final dist1x = CameraSensorCalibrationService.calculateStadiametricDistance( targetRealHeightMeters: 2.70, reticulePixelHeight: 100.0, screenHeightPixels: 1000.0, zoomMultiplier: 1.0, ); final dist3x = CameraSensorCalibrationService.calculateStadiametricDistance( targetRealHeightMeters: 2.70, reticulePixelHeight: 100.0, screenHeightPixels: 1000.0, zoomMultiplier: 3.0, ); expect((dist3x / dist1x), closeTo(3.0, 0.001)); }); test('Incline distance calculation from pitch angle', () { // 10m flagpole observed at 45° elevation final res = CameraSensorCalibrationService.calculateInclineDistance( targetRealHeightMeters: 10.0, pitchDegrees: 45.0, ); expect(res['groundDistance']!, closeTo(10.0, 0.1)); expect(res['slantRange']!, closeTo(14.14, 0.2)); }); test('AngleFormatter uses "الاتجاه" instead of "السمت"', () { final headingStr = AngleFormatter.format(45.0, AngleUnit.degrees); expect(headingStr, contains('الاتجاه')); expect(headingStr, isNot(contains('السمت'))); final milsStr = AngleFormatter.format(45.0, AngleUnit.mils); expect(milsStr, contains('الاتجاه')); expect(milsStr, isNot(contains('السمت'))); }); }); }