import 'dart:typed_data'; import 'package:abawo_bt_app/model/firmware_file_selection.dart'; import 'package:abawo_bt_app/model/shifter_types.dart'; import 'package:abawo_bt_app/service/firmware_file_selection_service.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { group('FirmwareFileSelectionService', () { test('prepares v1 metadata for selected .bin firmware', () async { final service = FirmwareFileSelectionService( filePicker: _FakeFirmwareFilePicker( selection: FirmwarePickerSelection( fileName: 'firmware.BIN', filePath: '/tmp/firmware.BIN', fileBytes: Uint8List.fromList([1, 2, 3, 4]), ), ), sessionIdGenerator: () => 0x1AB, ); final result = await service.selectAndPrepareDfuV1(); expect(result.isSuccess, isTrue); final firmware = result.firmware!; expect(firmware.fileName, 'firmware.BIN'); expect(firmware.filePath, '/tmp/firmware.BIN'); expect(firmware.fileBytes, [1, 2, 3, 4]); expect(firmware.metadata.totalLength, 4); expect(firmware.metadata.crc32, 0xB63CFBCD); expect(firmware.metadata.sessionId, 0xAB); expect(firmware.metadata.flags, universalShifterDfuFlagNone); }); test('returns canceled result when user dismisses picker', () async { final service = FirmwareFileSelectionService( filePicker: _FakeFirmwareFilePicker(selection: null), ); final result = await service.selectAndPrepareDfuV1(); expect(result.isSuccess, isFalse); expect(result.isCanceled, isTrue); expect(result.failure?.reason, FirmwareSelectionFailureReason.canceled); }); test('rejects unsupported extension', () async { final service = FirmwareFileSelectionService( filePicker: _FakeFirmwareFilePicker( selection: FirmwarePickerSelection( fileName: 'firmware.hex', fileBytes: Uint8List.fromList([1]), ), ), ); final result = await service.selectAndPrepareDfuV1(); expect(result.isSuccess, isFalse); expect(result.failure?.reason, FirmwareSelectionFailureReason.unsupportedExtension); }); test('rejects empty payload', () async { final service = FirmwareFileSelectionService( filePicker: _FakeFirmwareFilePicker( selection: FirmwarePickerSelection( fileName: 'firmware.bin', fileBytes: Uint8List(0), ), ), ); final result = await service.selectAndPrepareDfuV1(); expect(result.isSuccess, isFalse); expect(result.failure?.reason, FirmwareSelectionFailureReason.emptyFile); }); test('generates session id per run', () async { var nextSession = 9; final service = FirmwareFileSelectionService( filePicker: _FakeFirmwareFilePicker( selection: FirmwarePickerSelection( fileName: 'firmware.bin', fileBytes: Uint8List.fromList([10]), ), ), sessionIdGenerator: () => nextSession++, ); final first = await service.selectAndPrepareDfuV1(); final second = await service.selectAndPrepareDfuV1(); expect(first.firmware?.metadata.sessionId, 9); expect(second.firmware?.metadata.sessionId, 10); }); test('maps picker read failure to explicit validation error', () async { final service = FirmwareFileSelectionService( filePicker: _FakeFirmwareFilePicker( selection: null, error: const FormatException('broken pick payload'), ), ); final result = await service.selectAndPrepareDfuV1(); expect(result.isSuccess, isFalse); expect(result.failure?.reason, FirmwareSelectionFailureReason.readFailed); expect(result.failure?.message, contains('broken pick payload')); }); }); } class _FakeFirmwareFilePicker implements FirmwareFilePicker { _FakeFirmwareFilePicker({ required this.selection, this.error, }); final FirmwarePickerSelection? selection; final Object? error; @override Future pickFirmwareFile() async { if (error != null) { throw error!; } return selection; } }