feat: redesign and lots of progress

This commit is contained in:
2026-04-26 22:43:22 +02:00
parent 16ac66471a
commit 82ea8125e1
24 changed files with 1095 additions and 1315 deletions

View File

@ -0,0 +1,110 @@
import 'package:abawo_bt_app/model/shifter_types.dart';
import 'package:cbor/simple.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
group('CentralStatus.fromCborBytes', () {
test('decodes firmware packed status with FTMS ready', () {
final status = CentralStatus.fromCborBytes(
_packedStatusBytes(
controlVariant: 1,
trainerVariant: 5,
hasSavedBond: true,
connectedTrainerAddr: [1, 2, 3, 4, 5, 6],
),
);
expect(status.control, ControlConnectionState.connected);
expect(status.trainer.state, TrainerConnectionState.ftmsReady);
expect(status.trainer.errorCode, isNull);
expect(status.hasSavedBond, isTrue);
expect(status.connectedTrainerAddr, [1, 2, 3, 4, 5, 6]);
expect(status.lastFailure, isNull);
});
test('decodes all firmware packed trainer unit variants', () {
final expectedStates = <int, TrainerConnectionState>{
0: TrainerConnectionState.idle,
1: TrainerConnectionState.connecting,
2: TrainerConnectionState.pairing,
3: TrainerConnectionState.connected,
4: TrainerConnectionState.discoveringFtms,
5: TrainerConnectionState.ftmsReady,
6: TrainerConnectionState.error,
};
for (final entry in expectedStates.entries) {
final status = CentralStatus.fromCborBytes(
_packedStatusBytes(
controlVariant: 1,
trainerVariant: entry.key,
),
);
expect(
status.trainer.state,
entry.value,
reason: 'trainer variant ${entry.key} should decode correctly',
);
}
});
test('decodes firmware packed trainer error newtype variant', () {
final status = CentralStatus.fromCborBytes(
_packedStatusBytes(
controlVariant: 1,
trainerRaw: [6, errorFtmsRequiredCharMissing],
lastFailure: errorFtmsRequiredCharMissing,
),
);
expect(status.trainer.state, TrainerConnectionState.error);
expect(status.trainer.errorCode, errorFtmsRequiredCharMissing);
expect(status.lastFailure, errorFtmsRequiredCharMissing);
});
test('decodes non-packed status maps with text keys', () {
final status = CentralStatus.fromCborBytes(
cbor.encode({
'control': 'Connected',
'trainer': 'FtmsReady',
'has_saved_bond': false,
'connected_trainer_addr': [10, 11, 12, 13, 14, 15],
'last_failure': null,
}),
);
expect(status.control, ControlConnectionState.connected);
expect(status.trainer.state, TrainerConnectionState.ftmsReady);
expect(status.connectedTrainerAddr, [10, 11, 12, 13, 14, 15]);
});
test('throws for invalid status payloads instead of hiding them', () {
expect(
() => CentralStatus.fromCborBytes(const []),
throwsFormatException,
);
expect(
() => CentralStatus.fromCborBytes(cbor.encode([1, 2, 3])),
throwsFormatException,
);
});
});
}
List<int> _packedStatusBytes({
required int controlVariant,
int? trainerVariant,
Object? trainerRaw,
bool hasSavedBond = false,
List<int>? connectedTrainerAddr,
int? lastFailure,
}) {
return cbor.encode({
0: controlVariant,
1: trainerRaw ?? trainerVariant,
2: hasSavedBond,
3: connectedTrainerAddr,
4: lastFailure,
});
}

View File

@ -1,30 +1,18 @@
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility in the flutter_test package. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.
import 'package:abawo_bt_app/widgets/app_shell.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:abawo_bt_app/main.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(const AbawoBtApp());
testWidgets('renders app shell', (WidgetTester tester) async {
await tester.pumpWidget(
const MaterialApp(
home: AppShell(
currentLocation: '/devices',
child: Text('Devices'),
),
),
);
// Verify that our counter starts at 0.
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);
// Tap the '+' icon and trigger a frame.
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
// Verify that our counter has incremented.
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
expect(find.text('Devices'), findsWidgets);
});
}