import 'package:abawo_bt_app/model/gear_configurator.dart'; import 'package:abawo_bt_app/model/gear_ratio_codec.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { group('gear ratio codec', () { test('maps one byte across the configured drivetrain range', () { expect(decodeGearRatioByte(1), gearRatioMin); expect(decodeGearRatioByte(255), gearRatioMax); expect(encodeGearRatioByte(0), 0); expect(encodeGearRatioByte(gearRatioMax + 1), 255); }); test('quantizes ratios through the byte encoding', () { final quantized = quantizeGearRatio(50 / 11); expect(quantized, closeTo(4.55, 0.02)); expect(encodeGearRatioByte(quantized), encodeGearRatioByte(50 / 11)); }); }); group('calculateGearRatios', () { test('keep all deduplicates and sorts ascending', () { final result = calculateGearRatios( chainrings: [40, 20], sprockets: [20, 10], mode: GearRetentionMode.keepAll, ); expect(result.ratios, orderedEquals(result.ratios.toList()..sort())); expect(result.ratios.length, 3); expect(result.duplicateCount, 1); }); test('keep highest drops lower overlapping larger-chainring ratios', () { final result = calculateGearRatios( chainrings: [30, 50], sprockets: [10, 20, 30], mode: GearRetentionMode.keepHighest, ); expect(result.ratios.first, closeTo(1, 0.02)); expect(result.ratios.last, closeTo(5, 0.02)); expect(result.ratios.length, 4); expect(result.ratios.where((ratio) => ratio < 1).length, 0); }); test('discard ratios outside the one-byte range', () { final result = calculateGearRatios( chainrings: [20, 60], sprockets: [5, 100], mode: GearRetentionMode.keepAll, ); expect(result.discardedBelowRange, 1); expect(result.discardedAboveRange, 1); expect(result.ratios.length, 2); }); test('truncates to the configured maximum', () { final result = calculateGearRatios( chainrings: [30, 40, 50], sprockets: [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], mode: GearRetentionMode.keepAll, maxRatios: 8, ); expect(result.ratios.length, 8); expect(result.truncatedCount, greaterThan(0)); }); }); }